[med-svn] [SCM] ray branch, upstream, updated. upstream/2.1.0-6-geb605b7

Sébastien Boisvert sebastien.boisvert.3 at ulaval.ca
Sun Nov 4 15:24:15 UTC 2012


The following commit has been merged in the upstream branch:
commit eb605b7e0b2a431ce9a6be8d3fb5dddedadb28b8
Author: Sébastien Boisvert <sebastien.boisvert.3 at ulaval.ca>
Date:   Sun Nov 4 10:15:03 2012 -0500

    Imported Upstream version 2.1.0

diff --git a/Documentation/RELEASE_PROCEDURE.txt b/Documentation/RELEASE_PROCEDURE.txt
index c424f43..809dd4f 100644
--- a/Documentation/RELEASE_PROCEDURE.txt
+++ b/Documentation/RELEASE_PROCEDURE.txt
@@ -1,19 +1,13 @@
 * run regression tests (+backup on colosse)
 * run unit tests
-* compile with make
-* compile with cmake
-
-* update release list (Ray & RayPlatform)
 * check version in Makefile
 * ./Ray -help > MANUAL_PAGE.txt
+* compile with make
+* compile with cmake
 * git tag vx.y.z
 * do a tar.bz2 (ShipProduct), compile it (make + make install) and test it
-
 * upload the tarball on sf
 * update the web site (download + manual)
-
 * post an email on the list including changes (dump-changes)
 * update the seqanswer thread
-* Google+
-* Twitter
-* Facebook
+* update release list (Ray & RayPlatform)
diff --git a/Documentation/Releases.txt b/Documentation/Releases.txt
index ef0744c..ff7ff72 100644
--- a/Documentation/Releases.txt
+++ b/Documentation/Releases.txt
@@ -1,13 +1,13 @@
 Ray v2.1.0 "Ancient Granularity of Epochs" with RayPlatform v1.1.0 "Chariot of Complexity"
 Ray v2.0.0 "Dark Astrocyte of Knowledge" with RayPlatform v1.0.3 "Gray Pylon of Wisdom"
 Ray v1.7.0 "Magical Luminary of Celestial Bodies"
-Ray v1.6.1 "sunray"
+Ray v1.6.1
 Ray v1.6.0
 Ray v1.4.0
 Ray v1.3.0
-Ray v1.2.3 "cRAYfish"
-Ray v1.2.2 "X-ray"
-Ray v1.2.1 "stringray"
+Ray v1.2.3
+Ray v1.2.2
+Ray v1.2.1
 Ray v1.2.0
 Ray v1.0.0
 Ray v1.0.0
@@ -18,5 +18,5 @@ Ray v0.0.5
 Ray v0.0.4
 Ray v0.0.3
 Ray v0.0.2
-Ray v0.0.1 "Osiris"
-Ray v0.0.0 "crocodile"
+Ray v0.0.1
+Ray v0.0.0
diff --git a/Makefile b/Makefile
index 459419b..b6a8dad 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 1
-EXTRAVERSION = -devel
+SUBLEVEL = 0
+EXTRAVERSION =
 NAME = Ancient Granularity of Epochs
 
 # number of cores to use for compilation
diff --git a/RayPlatform b/RayPlatform
deleted file mode 120000
index 5eba77d..0000000
--- a/RayPlatform
+++ /dev/null
@@ -1 +0,0 @@
-../RayPlatform
\ No newline at end of file
diff --git a/RayPlatform/AUTHORS b/RayPlatform/AUTHORS
new file mode 100644
index 0000000..b3a4bfa
--- /dev/null
+++ b/RayPlatform/AUTHORS
@@ -0,0 +1,13 @@
+## Programmers
+
+- Sébastien Boisvert
+
+## Designers
+
+- Sébastien Boisvert
+- Élénie Godzaridis
+- Maxime Boisvert (suggested the use of a plugin architecture)
+
+## Code reviewers
+
+- Élénie Godzaridis
diff --git a/RayPlatform/CMakeLists.txt b/RayPlatform/CMakeLists.txt
new file mode 100644
index 0000000..31f8e8d
--- /dev/null
+++ b/RayPlatform/CMakeLists.txt
@@ -0,0 +1,57 @@
+cmake_minimum_required(VERSION 2.6 )
+
+set( CMAKE_CXX_COMPILER  mpicxx )
+set( CMAKE_CXX_FLAGS "-O3 -Wall -ansi" )
+
+include_directories( . )
+
+set( source_files
+
+handlers/MasterModeExecutor.cpp
+handlers/SlaveModeExecutor.cpp
+handlers/MessageTagExecutor.cpp
+core/master_modes.cpp
+core/ComputeCore.cpp
+core/slave_modes.cpp
+core/OperatingSystem.cpp
+core/statistics.cpp
+routing/GraphImplementationExperimental.cpp
+routing/GraphImplementationKautz.cpp
+routing/ConnectionGraph.cpp
+routing/GraphImplementation.cpp
+routing/GraphImplementationGroup.cpp
+routing/GraphImplementationComplete.cpp
+routing/GraphImplementationDeBruijn.cpp
+routing/GraphImplementationRandom.cpp
+routing/Hypercube.cpp
+scheduling/TaskCreator.cpp
+scheduling/SwitchMan.cpp
+scheduling/VirtualProcessor.cpp
+profiling/Derivative.cpp
+profiling/TimePrinter.cpp
+profiling/Profiler.cpp
+profiling/TickLogger.cpp
+cryptography/crypto.cpp
+structures/StaticVector.cpp
+memory/ReusableMemoryStore.cpp
+memory/ChunkAllocatorWithDefragmentation.cpp
+memory/DefragmentationGroup.cpp
+memory/RingAllocator.cpp
+memory/MyAllocator.cpp
+memory/allocator.cpp
+memory/DefragmentationLane.cpp
+plugins/CorePlugin.cpp
+plugins/RegisteredPlugin.cpp
+communication/VirtualCommunicator.cpp
+communication/MessagesHandler.cpp
+communication/MessageRouter.cpp
+communication/Message.cpp
+communication/mpi_tags.cpp
+communication/BufferedData.cpp
+
+)
+
+ADD_LIBRARY( RayPlatform_SHARED SHARED ${source_files})
+ADD_LIBRARY( RayPlatform_STATIC STATIC ${source_files})
+
+SET_TARGET_PROPERTIES( RayPlatform_SHARED RayPlatform_STATIC PROPERTIES OUTPUT_NAME RayPlatform )
diff --git a/RayPlatform/Documentation/ComputeCore.txt b/RayPlatform/Documentation/ComputeCore.txt
new file mode 100644
index 0000000..dc8e555
--- /dev/null
+++ b/RayPlatform/Documentation/ComputeCore.txt
@@ -0,0 +1,34 @@
+TUESDAY, JANUARY 17, 2012
+
+Ray Platform: a message-passing-interface programming framework
+The first pieces of Ray were put together in a git repository on 21 January 2010. Since that, Ray has undergo numerous major refactoring events.
+
+The biggest changes to date are those of a few days ago. The source code of Ray is now divided in Ray Platform (around 13000 source lines of code including comments and blank lines) and Ray Application (around 29 000 source lines of code including comments and blank lines).
+
+Ray Platform compiles independently of Ray Application -- it can be reused over and over again. I changed the license too. While Ray Application is still licensed under the GNU General Public License, version 3, Ray Platform is licensed under the GNU Lesser General Public License, version 3.
+
+This means that Ray Platform can be incorporated in proprietary software (for free, if that matters). If changes are made to Ray Platform, however, these have to be shared.
+
+How it works ?
+
+The main class of the Ray Platform is ComputeCore. It represents a process mapped to a single processor core. An instance of this class has a message inbox, a message outbox, a virtual processor and a virtual communicator. The programmer can use the application programming interface to register callbacks for message tags, slave modes and master modes.
+
+Message tag handlers
+
+Any MPI message tag (type of message) has a default callback method to handle it that does nothing at all. Let's say the MPI tag is called MPI_TAG_GET_COFFEE. The corresponding callback is call_MPI_TAG_GET_COFFEE. The empty callbacks are generated in MessageTagHandler automatically. To overwrite one, a class that inherits from MessageTagHandler has to be defined with the appropriate new handler (with the same name). Then, the programmer needs to register an instance of this new class as being the handler of the MPI tag.
+
+m_computeCore.setMessageTagObjectHandler(MPI_TAG_GET_COFFEE, &m_coffeeHandler);
+
+Henceforth, when a message is received, Ray Platform will call m_coffeeHandler.call_MPI_TAG_GET_COFFEE(message).
+
+
+Master and slave modes 
+
+In the Ray Platform, each ComputeCore has a current master mode and a current slave mode. The master mode of all ranks but the master is MASTER_RANK_DO_NOTHING. Just like for the message tags, the default handlers for slave modes and master modes can be overwritten with custom ones.
+
+
+Links
+
+Ray Platform
+Charm++
+Posted by Sébastien Boisvert at 9:39 AM
diff --git a/RayPlatform/Documentation/Handlers.txt b/RayPlatform/Documentation/Handlers.txt
new file mode 100644
index 0000000..62fe5b6
--- /dev/null
+++ b/RayPlatform/Documentation/Handlers.txt
@@ -0,0 +1,60 @@
+Modularity of Ray using handlers
+Sébastien Boisvert
+2011-01-16
+
+
+
+== Illustration ==
+
++--------------------------------------------------------------------------+
+|                                                                          |
+|                                Application                               |
+|                                                                          |
++------------------------+------------------------+------------------------+
+|                        |                        |                        |
+|         Plugin         |         Plugin         |         Plugin         |
+|                        |                        |                        |
++---------+---------+    +---------+---------+    +---------+---------+    +
+|         |         |    |         |         |    |         |         |    |
+| Adapter | Adapter |    | Adapter | Adapter |    | Adapter | Adapter |    |
+|         |         |    |         |         |    |         |         |    |
++---------+---------+----+---------+---------+----+---------+---------+----+
+|                                                                          |
+|                                RayPlatform                               |
+|                                                                          |
++--------------------------------------------------------------------------+
+|                                                                          |
+|                        Message Passing Interface                         |
+|                                                                          |
++--------------------------------------------------------------------------+
+
+In Ray, the code to execute that depends on slave modes, master modes, and message tags
+is handled by handlers.
+
+There are 3 handler classes:
+
+- MessageTagHandler
+- MasterModeHandler
+- SlaveModeHandler
+
+
+This makes Ray (or any application using the Ray platform) modular.
+
+== MACROS ==
+
+__CreatePlugin	
+	declares a static pointer to a plugin
+
+__CreateMasterModeAdapter	
+	generates an implementation for an adapter
+
+__CreateSlaveModeAdapter
+	generates an implementation for an adapter
+
+__CreateMessageTagAdapter
+	generates an implementation for an adapter
+
+__BindPlugin
+	sets the value of the static pointer to the plugin
+
+
diff --git a/RayPlatform/Documentation/Infiniband.txt b/RayPlatform/Documentation/Infiniband.txt
new file mode 100644
index 0000000..233782c
--- /dev/null
+++ b/RayPlatform/Documentation/Infiniband.txt
@@ -0,0 +1,13 @@
+The command ibv_devinfo provides information about Infiniband devices.
+
+To make sure that Open-MPI (if you use Open-MPI) detects the hardware and use
+RDMA.
+
+
+mpiexec \
+--mca btl_openib_verbose 1 \
+--mca mpi_show_mca_params all \
+--mca btl_openib_use_eager_rdma 1 \
+--mca btl_openib_mtu 4 \
+ -np 16 /home/sboisver12/Ray -o $jobName -test-network-only
+
diff --git a/RayPlatform/Documentation/MPI.txt b/RayPlatform/Documentation/MPI.txt
new file mode 100644
index 0000000..baebd8f
--- /dev/null
+++ b/RayPlatform/Documentation/MPI.txt
@@ -0,0 +1,102 @@
+== MPI ==
+
+MPI (Message Passing Interface) is a standard. It describes various functions that allow communication between MPI ranks. Given n MPI ranks, they are numbered from 0 to n-1. A message sent from a rank to another can transit on various media such as memory, shared memory, TCP/IP, Infiniband and others. However, the precise way that is utilized for the transfer is opaque to the programmer.
+
+In Ray, starting from version 1.0.0, the standard MPI 2.2 is used.
+
+
+
+
+No assumption is done in the code regarding the MPI implementation used, only
+the standard MPI 2.2 is considered.
+
+MPI 2.2  
+http://www.mpi-forum.org/docs/mpi-2.2/mpi22-report.pdf (PDF, 647 pages)
+
+== MPI 2.2 and Ray ==
+
+=== Chapter 2, MPI Terms and Conventions ===
+
+MPI_Init
+MPI_Get_processor_name
+MPI_Comm_rank
+MPI_Comm_size
+MPI_Finalize
+
+=== Chapter 3, Point to Point Communication ===
+
+MPI_Isend
+MPI_Recv
+MPI_Iprobe
+MPI_Get_count
+MPI_Request_free
+
+=== Chapter 4, Datatypes ===
+
+MPI_UNSIGNED_LONG_LONG
+MPI_Request
+MPI_Status
+
+=== Chapter 5, Collective Communications ===
+
+MPI_Barrier
+
+=== Chapter 6, Groups, Contexts, Communicators, and Caching ===
+
+MPI_COMM_WORLD
+
+== MPI implementations ==
+
+The code is tested with MPICH2 and Open-MPI, the two main implementations of the MPI standard.
+As I understand it, all other proprietary MPI libraries are based on MPICH2.
+
+MVAPICH2 is based too on MPICH2.
+
+Ray runs faster with MPICH2 than with Open-MPI.
+
+=== MPICH2 ===
+
+MPICH2
+http://www.mcs.anl.gov/research/projects/mpich2/
+License: BSD-like
+http://www.mcs.anl.gov/research/projects/mpich2/downloads/license.txt
+
+=== Open-MPI ===
+
+Open-MPI
+http://www.open-mpi.org/
+License: BSD 
+http://www.opensource.org/licenses/bsd-license.php
+
+
+== How messages are communicated around in Ray ? ==
+
+MPI_Isend is utilized to send messages. MPI_Recv is utilized to receive them.
+MPI_Iprobe is utilized to check for incoming messages.
+
+All the MPI messages are sent and received exclusively in MessagesHandler.cpp.
+After MPI_Isend, the MPI_Request is immediately freed using MPI_Request_free.
+
+A ring buffer (RingAllocator.cpp) is utilized to allocate space for message buffers.
+This allocated space never exceeds 4096 bytes. This is a design decision.
+
+For many part of the code, messages are buffered with instances of BufferedData.cpp.
+When the threshold is reached, buffers are flushed and resetted.
+
+In the cases where an MPI rank just send MPI messages without requiring answers from other MPI ranks, the MPI rank waits for a reply before sending the next message. This strategy ensures that the ring buffer is not abused. Furthermore, the motivation for this is that resources for accomodating incoming messages in the MPI library side are very finite.
+
+== I want to learn more on MPI ! ==
+
+RS/6000 SP: Practical MPI Programming
+http://www.redbooks.ibm.com/redbooks/pdfs/sg245380.pdf
+
+IBM MPI Programming Guide
+http://www.pik-potsdam.de/~bloh/pdffile/pe_mpi_prog_guide_v3r10.pdf
+
+Best books to learn MPI programming
+http://stackoverflow.com/questions/1617624/best-books-to-learn-mpi-programming
+
+MPI 2.2  
+http://www.mpi-forum.org/docs/mpi-2.2/mpi22-report.pdf (PDF, 647 pages)
+
+
diff --git a/RayPlatform/Documentation/Message-Data-Reliability.txt b/RayPlatform/Documentation/Message-Data-Reliability.txt
new file mode 100644
index 0000000..58d9cf6
--- /dev/null
+++ b/RayPlatform/Documentation/Message-Data-Reliability.txt
@@ -0,0 +1,16 @@
+
+Adding the option -verify-message-integrity will add a verification
+for any non-empty message.
+
+The CRC32 algorithm is used.
+
+If you have a processor that supports SSE 4.2, then you can compile with
+CONFIG_SSE_4_2 (just add -D CONFIG_SSE_4_2 in the Makefile, for
+example) to do the CRC32 on the hardware for more speedy results.
+
+The hardware-accelerated code for CRC32 was written by Benjamin Kittridge
+and is distributed on his blog at http://byteworm.com/2010/10/13/crc32/
+
+
+
+
diff --git a/RayPlatform/Documentation/Message-Routing.txt b/RayPlatform/Documentation/Message-Routing.txt
new file mode 100644
index 0000000..527cae5
--- /dev/null
+++ b/RayPlatform/Documentation/Message-Routing.txt
@@ -0,0 +1,34 @@
+Having too many connections can be bad.
+
+Let's say we have 64 ranks.
+
+Let's say that we want the ranks to be grouped in 8.
+
+
+Then, when rank 3 want to send a message to rank 55, it is required
+to get the intermediate ranks.
+
+
+rank 3 -> intermediate(rank 3) -> intermediate(rank 55) -> rank 55
+
+
+
+rank 3 sends to rank 0
+rank 0 sends to rank 48
+rank 3 sends to rank 0
+rank 0 sends to rank 48
+rank 48 sends to rank 55
+rank 48 sends to rank 55
+
+To route messages with Ray, you need to provide the option -route-messages.
+
+You can also provide the type using -connection-type <type>
+
+== Connection types ==
+
+- complete (same as not using -route-messages)
+- group (as described above, not really good because it is not balanced)
+- random (the graph has random n*log2(n)/2 edges)
+- debruijn (better than random, but needs a power of something)
+- kautz (better than debruijn, but needs n ranks where n=(k+1)*k^(d-1) where k and d are two integers.
+
diff --git a/RayPlatform/Documentation/Releases.txt b/RayPlatform/Documentation/Releases.txt
new file mode 100644
index 0000000..62a6241
--- /dev/null
+++ b/RayPlatform/Documentation/Releases.txt
@@ -0,0 +1,6 @@
+RayPlatform v1.1.0 "Chariot of Complexity"
+RayPlatform v1.0.3 "Gray Pylon of Wisdom"
+RayPlatform v1.0.2 "Timely Gate of Yields"
+RayPlatform v1.0.1 "Time-distributed Prism"
+RayPlatform v1.0 "Parallel Soy Sauce"
+
diff --git a/RayPlatform/Documentation/VirtualCommunicator.txt b/RayPlatform/Documentation/VirtualCommunicator.txt
new file mode 100644
index 0000000..5a84645
--- /dev/null
+++ b/RayPlatform/Documentation/VirtualCommunicator.txt
@@ -0,0 +1,111 @@
+Date: 2011-08-25
+Author: Sébastien Boisvert
+Subject: VirtualCommunicator
+Written on: VIA train 60 (Toronto -> Montréal)
+
+
+The standard way of starting a program in the
+command-line prompt is:
+
+	./MyProgram
+
+If MyProgram utilises threads and the systems has more than 1 processor logical
+core, then MyProgram may use them if needed and/or was designed to.
+
+
+== On the way to passing messages ==
+
+
+When using the message-passing interface (MPI), a program built around it can be
+run on more than one processor logical core. 
+
+With the message-passing interface, a program is started using an
+auxiliary program. Its standard name is mpiexec, and this name stands for
+Message-Passing-Interface EXECution (or perhaps EXEcuter). Other names for such an auxiliary program
+are mpirun and orterun. With mpiexec, the same program (in our example that
+would be MyProgram) is started on numerous processor logical cores and each of
+these program instances is given a unique identifier. Each of these numbered
+running instances are called MPI ranks. The identifying numbers of 4 MPI ranks
+would be 0, 1, 2 and 3. To start a program within this framework, the following
+command must be utilised:
+
+	mpiexec -n 4 ./MyProgram
+
+Basically, this mpiexec program will take start the same program 4 times. The
+magic of this is that the 4 MPI ranks can be on different computers, thus
+enabling the true potential of compute clusters with distributed resources. For
+instance, 16 computers connected with an Internet protocol (TCP/IP) network is a
+compute cluster with distributed resources. Let's assume that each has 8
+processor logical cores. In the MPI world, it means that we can have 
+8 MPI ranks per computer. 16 computers thus give a total of 16*8 = 128 MPI
+ranks.
+
+
+== Sending and receiving information ==
+
+It would be obviously pointless to start several instance of the same program
+with the same exact command-line arguments if these can not exchange
+information.
+
+Fortunately, there is one single thing that truly differentiate all these
+otherwise identical running instances of the same program executable. This handy
+attribute that I refer to is these MPI rank numbers. Using these, any MPI rank
+can send a message to another specific MPI rank. And any MPI rank can check for
+new unread messages recently received.
+
+Any message thus has a sender MPI rank, a receiver MPI rank and actual
+information. Any message also has an MPI tag to identify the type of information
+it contains.
+
+The hardest part is presumably to implement programs using this general idea of
+MPI ranks. Following the single-program multiple-data paradigm (SPMD), the source
+code of a MPI program is the same regardless of the actual number of a MPI rank.
+
+Indeed, when started, each MPI rank gets 2 important values from mpiexec. The first is its MPI
+rank number that we already discussed above. The second is the total number of
+MPI ranks, which we also discussed above.
+
+
+== Sending messages is the bottleneck ==
+
+Communicating messages enables the creation of truly parallel and distributed
+computational systems. But sending messages will be slowest part in your code on
+most hardware.
+
+	see mpi-communication-latency.txt
+
+
+== VirtualCommunicator ==
+
+Let's say that MPI rank 4 needs to send 500 messages, each having 8 bytes of data,
+to MPI rank 13. And let's also assume that all these messages have the same MPI tag.
+
+Assuming that the maximum size of a single message is 4000 bytes, all these 500
+messages can be agglomerated in one large message of 4000 bytes (500 * 8 = 4000).
+
+The idea of the VirtualCommunicator is to push each of these small 500 messages
+individually to a virtual communication device. This way, the programmer does
+not need to care about actually grouping its messages at all. This can be tricky
+and/or boring to do manually in the code. 
+
+This so-called VirtualCommunicator will do the multiplexing and de-multiplexing
+of all message contents.
+
+== Implementation ==
+
+Author: Sébastien Boisvert
+License: GPL
+code/communication/VirtualCommunicator.h
+code/communication/VirtualCommunicator.cpp
+
+= Feeding the VirtualCommunicator ==
+
+Effectively write code that can push a lot of small messages on the
+VirtualCommunicator is also easy. You simply have to split the work load in
+slices. 
+
+Then, you have to assign each of these slices to a single worker.
+
+	see VirtualProcessor.txt
+
+
diff --git a/RayPlatform/Documentation/VirtualProcessor.txt b/RayPlatform/Documentation/VirtualProcessor.txt
new file mode 100644
index 0000000..7f6dff7
--- /dev/null
+++ b/RayPlatform/Documentation/VirtualProcessor.txt
@@ -0,0 +1,61 @@
+Date: 2011-08-25
+Author: Sébastien Boisvert
+Subject: VirtualProcessor
+Written on: VIA train 60 (Toronto -> Montréal)
+
+
+The VirtualProcessor I developed enables any MPI rank to have thousands of workers working
+on different tasks. In reality, only one worker can work at any given moment, but
+the VirtualProcessor schedules fairly the workers on the only instruction pipeline
+available so that is not a problem at all.
+
+
+The VirtualProcessor is a technology that make thousands of worker compute tasks
+in parallel on a single MPI rank. Obviously, only one such worker is active at
+any point, but they all get to work.
+
+The idea is that when a worker pushes a message on the VirtualCommunicator, it has
+to wait for a reply. And this reply may arrive later. The idea of the
+VirtualProcessor is to easily submit communication-intensive tasks. 
+
+Basically, the VirtualCommunicator groups smaller messages into larger messages
+to send fewer messages on the physical network.
+
+But to achieve that, an easy way of generating a lot of small messages is
+needed. This is the use of the VirtualProcessor.
+
+
+== Implementation ==
+
+Author: Sébastien Boisvert
+License: GPL
+code/scheduling/VirtualProcessor.h
+code/scheduling/VirtualProcessor.cpp
+
+
+== Workers ==
+
+In Ray, each MPI rank actually has thousands of workers within it. All these
+workers are scheduled, one after the other, inside the same process. No thread
+are utilised as these would trash the processor cache. 
+
+At any point in time, each of these worker is in one of these states:
+
+- active;
+- sleeping;
+- completed.
+
+
+
+active 
+
+	The worker is not waiting for a message reply.
+
+sleeping
+
+	The worker is waiting for a message reply.
+
+completed
+
+	The worker has completed its task.
+
diff --git a/RayPlatform/Documentation/communication-design.txt b/RayPlatform/Documentation/communication-design.txt
new file mode 100644
index 0000000..be16a13
--- /dev/null
+++ b/RayPlatform/Documentation/communication-design.txt
@@ -0,0 +1,120 @@
+= Master modes, slave modes, master methods & slave methods =
+
+One MPI rank has a master mode and a slave mode. The master mode is set initially to MASTER_MODE_DO_NOTHING for all MPI ranks except the 0, which is the only master. The slave mode is set initially to MODE_DO_NOTHING.
+
+Note that the master is also a slave, so given n MPI ranks, there is 1 master and n slaves.
+
+In Machine.cpp, functions with a name starting with call_MASTER_MODE_ are master methods. There are 25 such methods.
+
+In the same file, functions with a name starting with call_MODE_ are slave methods. There are 16 such methods.
+
+Two arrays, namely m_master_methods and m_slave_methods, contain pointers to master and slave methods, respectively.
+
+Selecting the master method given the master mode is done in constant time, and so is the selection of the slave method.
+
+
+= MPI message tags =
+
+
+There are over one hundred MPI tags in Ray (113 to be exact).
+
+In MessageProcessor.cpp, functions with a name starting with call_TAG_ are message handlers. There are 113 such methods.
+
+In the same file, there is an array indexing the message handlers so that given a message, the correct message handler is selected in constant time.
+
+= Implementation =
+
+* 53 C++ classes
+* 48 .cpp files
+* 55 .h files
+
+= libRay.a =
+
+This is the Ray library.
+
+== with MPICH2 (MPICH2 is a static library) ==
+<pre>
+[boi at ls30 code]$ file libRay.a 
+libRay.a: current ar archive
+
+[boi at ls30 code]$ ls -l libRay.a 
+-rw-rw-r-- 1 boiseb01 boiseb01 798910 2010-11-21 17:45 libRay.a
+
+</pre>
+
+==  with Open-MPI (Open-MPI is a shared library) ==
+<pre>
+[boi at ls30 code]$ file libRay.a 
+libRay.a: current ar archive
+
+[boi at ls30 code]$ ls -l libRay.a  
+-rw-rw-r-- 1 boiseb01 boiseb01 2835066 2010-11-21 17:39 libRay.a
+</pre>
+
+= the Ray a.out (executable) =
+
+Ray is the sole executable necessary for assembling data.
+
+== with MPICH2 ==
+<pre>
+
+[boi at ls30 code]$ file Ray
+Ray: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
+
+[boi at ls30 code]$ ls -l Ray
+-rwxrwxr-x 1 boiseb01 boiseb01 1176749 2010-11-21 17:45 Ray
+
+</pre>
+
+== with Open-MPI ==
+
+<pre>
+
+[boi at ls30 code]$ file Ray
+Ray: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
+
+[boi at ls30 code]$ ls -l Ray
+-rwxrwxr-x 1 boiseb01 boiseb01 464782 2010-11-21 17:39 Ray
+
+</pre>
+
+= External libraries =
+
+It is linked with several libraries.
+
+== with MPICH2 ==
+<pre>
+[boi at ls30 code]$ ldd Ray
+	linux-vdso.so.1 =>  (0x00007fff733ff000)
+	libz.so.1 => /lib64/libz.so.1 (0x00000033f6600000)
+	libbz2.so.1 => /lib64/libbz2.so.1 (0x0000003403e00000)
+	librt.so.1 => /lib64/librt.so.1 (0x00000033f6e00000)
+	libpthread.so.0 => /lib64/libpthread.so.0 (0x00000033f5e00000)
+	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003404600000)
+	libm.so.6 => /lib64/libm.so.6 (0x00000033f5600000)
+	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003401a00000)
+	libc.so.6 => /lib64/libc.so.6 (0x00000033f5200000)
+	/lib64/ld-linux-x86-64.so.2 (0x00000033f4e00000)
+</pre>
+
+== with Open-MPI ==
+
+<pre>
+[boi at ls30 code]$ ldd Ray
+	linux-vdso.so.1 =>  (0x00007fff74347000)
+	libz.so.1 => /lib64/libz.so.1 (0x00000033f6600000)
+	libbz2.so.1 => /lib64/libbz2.so.1 (0x0000003403e00000)
+	libmpi_cxx.so.0 => /home/boiseb01/software/ompi-1.4.1-gcc/lib/libmpi_cxx.so.0 (0x00007f35ec545000)
+	libmpi.so.0 => /home/boiseb01/software/ompi-1.4.1-gcc/lib/libmpi.so.0 (0x00007f35ec2a4000)
+	libopen-rte.so.0 => /home/boiseb01/software/ompi-1.4.1-gcc/lib/libopen-rte.so.0 (0x00007f35ec059000)
+	libopen-pal.so.0 => /home/boiseb01/software/ompi-1.4.1-gcc/lib/libopen-pal.so.0 (0x00007f35ebde7000)
+	libdl.so.2 => /lib64/libdl.so.2 (0x00000033f5a00000)
+	libnsl.so.1 => /lib64/libnsl.so.1 (0x0000003404a00000)
+	libutil.so.1 => /lib64/libutil.so.1 (0x0000003402200000)
+	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003404600000)
+	libm.so.6 => /lib64/libm.so.6 (0x00000033f5600000)
+	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003401a00000)
+	libpthread.so.0 => /lib64/libpthread.so.0 (0x00000033f5e00000)
+	libc.so.6 => /lib64/libc.so.6 (0x00000033f5200000)
+	/lib64/ld-linux-x86-64.so.2 (0x00000033f4e00000)
+</pre>
diff --git a/RayPlatform/Documentation/hyperthreading.txt b/RayPlatform/Documentation/hyperthreading.txt
new file mode 100644
index 0000000..aaf178d
--- /dev/null
+++ b/RayPlatform/Documentation/hyperthreading.txt
@@ -0,0 +1,21 @@
+Ray works well with Intel Hyper Threading (HT) Technology.
+
+If the cluster nodes have HT enabled (in bios and in the operating system), then
+you can schedule Ray on all the logical cores.
+
+== Example ==
+
+A Xeon Nehalem <something> has 4 physical cores.
+Each core has two threads visible by the operating system, but both utilise the
+same space on the chip.
+
+If you have 5 computers and each has 2 Xeon Nehalem <something> processors,
+then each computer has 8 physical cores and 16 logical cores.
+
+Basically, you can start Ray with 5*16 MPI ranks instead of 5*8 MPI ranks.
+
+== Default value ==
+
+By default, almost all clusters have the HT disabled in the bios.
+
+
diff --git a/RayPlatform/Documentation/interconnects.txt b/RayPlatform/Documentation/interconnects.txt
new file mode 100644
index 0000000..ac194f9
--- /dev/null
+++ b/RayPlatform/Documentation/interconnects.txt
@@ -0,0 +1,37 @@
+
+Hardware: QLogic Infiniband QDR
+Operating system: CentOS GNU/Linux
+Scheduler: Portable Batch System/MOAB
+Compiler: gcc 4.x
+Middleware: MVAPICH2 1.6
+Processor: Intel Xeon Nehalem
+Latency: 15 microseconds
+
+Hardware: Mellanox Infiniband QDR
+Operating system: CentOS GNU/Linux
+Scheduler: Sun Grid Engine
+Compiler: gcc 4.x
+Middleware: Open-MPI 1.4.3
+Processor: Intel Xeon Nehalem
+Latency: 180 microseconds
+
+Hardware: giga ethernet
+Operating system: Debian GNU/Linux
+Compiler: gcc 4.x
+Middleware: Open-MPI 1.3.X
+Processor: Intel Xeon Nehalem
+Latency: 600 microseconds
+
+Hardware: shared memory
+Operating system: Ubuntu GNU/Linux 32 bits
+Compiler: gcc 4.5.2
+Middleware: Open-MPI 1.4.3
+Processor: Intel Atom (Samsung NF210)
+Latency: 50 microseconds
+
+Hardware: shared memory
+Operating system: Fedora
+Compiler: gcc 4.x
+Middleware: Open-MPI 1.4.3
+Processor: AMD Opteron
+Latency: x microseconds
diff --git a/RayPlatform/Documentation/mpi-communication-latency.txt b/RayPlatform/Documentation/mpi-communication-latency.txt
new file mode 100644
index 0000000..bddb58b
--- /dev/null
+++ b/RayPlatform/Documentation/mpi-communication-latency.txt
@@ -0,0 +1,28 @@
+The latency (in microseconds) includes:
+
+(starting with with Ray's software layer and ending with physics)
+
+[user-space software layer]
+
+- Ray's code in general (number of ticks per second in Ray's main loop);
+- Ray'S VirtualProcessor;
+- Ray's VirtualCommunicator;
+- Ray's MPI wrapping code;
+
+[middleware layer]
+
+- middleware (MPICH2, Open-MPI or another MPI implementation);
+
+[kernel-space layer]
+
+- kernel page fault handling, if any;
+- kernel cache miss handling, if any;
+- process context switching (kernel process scheduling);
+- kernel hardware drivers (Infiniband OFED or other drivers);
+
+[hardware layer]
+
+- hardware firmware, if any
+- hardware (Infiniband, TCP/IP or or other);
+- actual congestion state of communication routes
+- physics involved in moving photons and/or electrons over physical distances
diff --git a/RayPlatform/Documentation/parallel-framework.txt b/RayPlatform/Documentation/parallel-framework.txt
new file mode 100644
index 0000000..e809c93
--- /dev/null
+++ b/RayPlatform/Documentation/parallel-framework.txt
@@ -0,0 +1,27 @@
+Ray is a lock-free software.
+
+
+scheduling/VirtualProcessor is a virtual processor, see VirtualProcessor.txt
+
+scheduling/TaskCreator.h is an interface to create task creators for the virtual processor
+
+scheduling/Worker is an interface to define workers
+
+
+workers communicate with the virtual communicator and not directly the outbox and inbox
+
+
+
+# Purging dead edges
+
+class EdgePurger : public TaskCreator 
+
+class EdgePurgerWorker : public Worker 
+
+
+# Merging similar paths
+
+class FusionTaskCreator: public TaskCreator
+
+class FusionWorker: public Worker
+
diff --git a/RayPlatform/Documentation/plugins.txt b/RayPlatform/Documentation/plugins.txt
new file mode 100644
index 0000000..2d3b052
--- /dev/null
+++ b/RayPlatform/Documentation/plugins.txt
@@ -0,0 +1,4 @@
+
+The application programming interface for plugins is all in the class ComputeCore.
+
+see RayPlatform/core/ComputeCore.h
diff --git a/RayPlatform/Documentation/profiling.txt b/RayPlatform/Documentation/profiling.txt
new file mode 100644
index 0000000..a39ccaa
--- /dev/null
+++ b/RayPlatform/Documentation/profiling.txt
@@ -0,0 +1,19 @@
+
+Compile Ray with
+
+
+Run Ray with -run-profiler
+
+
+Extract profiling information
+
+	grep "from previous" coli.Log |awk '{print $4" "$9" "$10" "$11" "$14}' > stats
+
+
+Remove the +
+
+	sed -i 's/+//g' stats
+
+Sort the entries:
+
+	cat stats|sort -n -r|less
diff --git a/code/DoxygenConfigurationFile b/RayPlatform/DoxygenConfigurationFile
similarity index 99%
copy from code/DoxygenConfigurationFile
copy to RayPlatform/DoxygenConfigurationFile
index f81f1ed..82ded4f 100644
--- a/code/DoxygenConfigurationFile
+++ b/RayPlatform/DoxygenConfigurationFile
@@ -25,7 +25,7 @@ DOXYFILE_ENCODING      = UTF-8
 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded
 # by quotes) that should identify the project.
 
-PROJECT_NAME           = Ray
+PROJECT_NAME           = Ray Platform
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
 # This could be handy for archiving the generated documentation or
@@ -38,7 +38,7 @@ PROJECT_NUMBER         = 1
 # If a relative path is entered, it will be relative to the location
 # where doxygen was started. If left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = Ray-Documentation
+OUTPUT_DIRECTORY       = RayPlatform-Documentation
 
 # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
 # 4096 sub-directories (in 2 levels) under the output directory of each output
diff --git a/RayPlatform/Makefile b/RayPlatform/Makefile
new file mode 100644
index 0000000..2db2a9d
--- /dev/null
+++ b/RayPlatform/Makefile
@@ -0,0 +1,27 @@
+# author: Sébastien Boisvert
+#
+# based on http://www.ravnborg.org/kbuild/makefiles.html
+#
+
+VERSION = 1
+PATCHLEVEL = 1
+SUBLEVEL = 0
+EXTRAVERSION = 
+NAME = Chariot of Complexity
+
+RAYPLATFORM_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+
+include common.mk
+
+all: libRayPlatform.a
+
+libRayPlatform.a: $(obj-y)
+	$(AR) rcs $@ $^
+
+# inference rule
+%.o: %.cpp
+	$(MPICXX) $(CXXFLAGS) -D RAYPLATFORM_VERSION=\"$(RAYPLATFORM_VERSION)\" -I. -c -o $@ $<
+
+clean:
+	$(RM) -f libRayPlatform.a $(obj-y)
+
diff --git a/RayPlatform/Makefile.shared-gcc b/RayPlatform/Makefile.shared-gcc
new file mode 100644
index 0000000..fcfa947
--- /dev/null
+++ b/RayPlatform/Makefile.shared-gcc
@@ -0,0 +1,19 @@
+# author: Sébastien Boisvert
+#
+# based on http://www.ravnborg.org/kbuild/makefiles.html
+#
+
+include common.mk
+
+all: libRayPlatform.so
+
+libRayPlatform.so: $(obj-y)
+	$(MPICXX) -shared -Wl,-soname,libRayPlatform.so -o libRayPlatform.so $(obj-y) -lc
+
+# inference rule
+%.o: %.cpp
+	$(MPICXX) -fPIC $(CXXFLAGS) -I. -c -o $@ $< 
+
+clean:
+	$(RM) -f libRayPlatform.so $(obj-y)
+
diff --git a/RayPlatform/README b/RayPlatform/README
new file mode 100644
index 0000000..a52cc5b
--- /dev/null
+++ b/RayPlatform/README
@@ -0,0 +1,96 @@
+RayPlatform is a development framework to ease the creation of 
+massively distributed high performance computing applications.
+
+Content creation is done by creating plugins that can be 
+added on the RayPlatform compute engine.
+
+It uses the message-passing interface for interprocess communication, but this is
+transparent to the developer.
+
+## Illustration 
+
++--------------------------------------------------------------------------+
+|                                                                          |
+|                                Application                               |
+|                                                                          |
++------------------------+------------------------+------------------------+
+|                        |                        |                        |
+|         Plugin         |         Plugin         |         Plugin         |
+|                        |                        |                        |
++---------+---------+    +---------+---------+    +---------+---------+    +
+|         |         |    |         |         |    |         |         |    |
+| Adapter | Adapter |    | Adapter | Adapter |    | Adapter | Adapter |    |
+|         |         |    |         |         |    |         |         |    |
++---------+---------+----+---------+---------+----+---------+---------+----+
+|                                                                          |
+|                                RayPlatform                               |
+|                                                                          |
++--------------------------------------------------------------------------+
+|                                                                          |
+|                        Message Passing Interface                         |
+|                                                                          |
++--------------------------------------------------------------------------+
+
+## Projects using RayPlatform 
+
+- The Ray genome assembler
+	http://github.com/sebhtml/ray
+- RayPlatform example
+	http://github.com/sebhtml/RayPlatform-example
+- MessageWarden
+	http://github.com/sebhtml/MessageWarden
+
+## Description 
+
+There is some documentation in Documentation/
+
+You can also generate doxygen documentation.
+
+The framework provides facilities for parallel software architecture,
+communication, memory management, profiling, thread pools 
+and some structures.
+
+It can be compiled as libRayPlatform.a, libRayPlatform.so or libRayPlatform.dll
+using GNU Make or CMake.
+
+
+### Parallel software architecture:
+
+- a compute core implementation in which the main loop lives (core/ComputeCore.h);
+- a system of plugins that can be registered with the ComputeCore (core/CorePlugin.h);
+- a system of callbacks for message tags (handlers/MessageTagHandler.h);
+- a system of callbacks for master modes (handlers/MasterModeHandler.h);
+- a system of callbacks for slave modes (handlers/SlaveModeHandler.h);
+- a system for master switches (scheduling/Switchman.h)
+- a system for slave switches (scheduling/Switchman.h)
+
+### Communication:
+
+- a message inbox and outbox (structures/StaticVector.h);
+- a virtual communicator for automated message aggregation (communication/VirtualCommunicator.h);
+- a buffered data object for less-automated message aggregation (communication/BufferedData.h);
+- a message router (including various graphs such as de Bruijn) 
+  for jobs running on numerous cores (> 1000) (communication/MessageRouter.h and routing/*);
+- a wrapper on top of the provided MPI library (communication/MessagesHandler.h).
+
+### Memory management:
+
+- a ring allocator (memory/RingAllocator.h);
+- a "chunk" allocator (memory/MyAllocator.h);
+- an allocator with real-time defragmentation (memory/ChunkAllocatorWithDefragmentation.h).
+
+### Profiling:
+
+- a profiler that reports granularity (profiling/Profiler.h);
+- a tick counter for slave and master modes (profiling/TickLogger.h);
+
+### Thread pools:
+
+- a virtual processor containing a lot of workers (scheduling/VirtualProcessor.h);
+- a general interface to define a worker (scheduling/Worker.h);
+- a general way to use the virtual processor (scheduling/TaskCreator.h).
+
+### Structures:
+
+- very space-efficient sparse hash table (structures/MyHashTable.h);
+- a splay tree (structures/SplayTree.h).
diff --git a/RayPlatform/common.mk b/RayPlatform/common.mk
new file mode 100644
index 0000000..f6f1bb3
--- /dev/null
+++ b/RayPlatform/common.mk
@@ -0,0 +1,63 @@
+MPICXX = mpicxx
+AR = ar
+CXXFLAGS= -O3 -Wall -ansi
+RM = rm
+
+#memory
+obj-y += memory/ReusableMemoryStore.o memory/MyAllocator.o memory/RingAllocator.o 
+obj-y += memory/allocator.o
+obj-y += memory/DefragmentationGroup.o memory/ChunkAllocatorWithDefragmentation.o memory/DefragmentationLane.o
+
+# routing stuff for option -route-messages
+#
+obj-y += routing/GraphImplementation.o
+obj-y += routing/GraphImplementationRandom.o
+obj-y += routing/GraphImplementationComplete.o
+obj-y += routing/GraphImplementationDeBruijn.o
+obj-y += routing/GraphImplementationKautz.o
+obj-y += routing/GraphImplementationExperimental.o
+obj-y += routing/GraphImplementationGroup.o
+obj-y += routing/Hypercube.o
+obj-y += routing/ConnectionGraph.o
+
+#communication
+obj-y += communication/mpi_tags.o communication/VirtualCommunicator.o communication/BufferedData.o \
+communication/Message.o  communication/MessagesHandler.o
+obj-y += communication/MessageRouter.o
+
+# scheduling stuff
+obj-y += scheduling/VirtualProcessor.o
+obj-y += scheduling/TaskCreator.o
+obj-y += scheduling/SwitchMan.o
+
+#core
+obj-y += core/slave_modes.o 
+obj-y += core/OperatingSystem.o
+obj-y += core/master_modes.o
+obj-y += core/ComputeCore.o
+obj-y += core/statistics.o
+
+# plugin architecture
+
+obj-y += plugins/CorePlugin.o
+obj-y += plugins/RegisteredPlugin.o
+
+# structures
+obj-y += structures/StaticVector.o 
+
+# profiling
+obj-y += profiling/Profiler.o
+obj-y += profiling/Derivative.o
+obj-y += profiling/TickLogger.o
+obj-y += profiling/TimePrinter.o
+
+# handlers
+
+obj-y += handlers/MasterModeExecutor.o
+obj-y += handlers/SlaveModeExecutor.o
+obj-y += handlers/MessageTagExecutor.o
+
+#cryptography
+obj-y += cryptography/crypto.o
+
+
diff --git a/RayPlatform/communication/BufferedData.cpp b/RayPlatform/communication/BufferedData.cpp
new file mode 100644
index 0000000..fca4c1d
--- /dev/null
+++ b/RayPlatform/communication/BufferedData.cpp
@@ -0,0 +1,200 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <communication/BufferedData.h>
+#include <memory/RingAllocator.h>
+#include <memory/allocator.h>
+#include <structures/StaticVector.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <iostream>
+using namespace std;
+
+// the capacity is measured in uint64_t
+void BufferedData::constructor(int numberOfRanks,int capacity,const char*type,bool show,int period){
+	m_period=period;
+	m_flushedMessages=0;
+	m_count=0;
+	m_pushedMessages=0;
+	m_show=show;
+	strcpy(m_type,type);
+
+	#ifdef DEBUG_BUFFERS
+	printf("BufferedData::constructor\n");
+	fflush(stdout);
+	#endif
+
+	m_sizes=(int*)__Malloc(sizeof(int)*numberOfRanks,m_type,m_show);
+	m_data=(MessageUnit*)__Malloc(sizeof(MessageUnit)*capacity*numberOfRanks,m_type,m_show);
+	for(int i=0;i<(int)numberOfRanks;i++){
+		m_sizes[i]=0;
+	}
+	m_capacity=capacity;
+	m_ranks=numberOfRanks;
+}
+
+void BufferedData::clear(){
+	#ifdef ASSERT
+	assert(isEmpty());
+	#endif
+
+	if(m_sizes!=NULL){
+		__Free(m_sizes,m_type,m_show);
+		m_sizes=NULL;
+	}
+	if(m_data!=NULL){
+		__Free(m_data,m_type,m_show);
+		m_data=NULL;
+	}
+}
+
+int BufferedData::size(int i)const{
+	#ifdef ASSERT
+	if(i>=m_ranks){
+		cout<<"i="<<i<<" m_ranks="<<m_ranks<<endl;
+	}
+	assert(i<m_ranks);
+	#endif
+	return m_sizes[i];
+}
+
+MessageUnit BufferedData::getAt(int i,int j){
+	return m_data[i*m_capacity+j];
+}
+
+void BufferedData::addAt(int i,MessageUnit k){
+	int j=size(i);
+	m_data[i*m_capacity+j]=k;
+	m_sizes[i]++;
+	m_count++;
+	if(m_count==m_period){
+		m_count=0;
+		m_pushedMessages++;
+	}
+}
+
+void BufferedData::reset(int i){
+	m_sizes[i]=0;
+	#ifdef ASSERT
+	assert(m_sizes[i]==0);
+	#endif
+}
+
+bool BufferedData::isEmpty()const{
+	if(m_sizes==NULL&&m_data==NULL){
+		return true;
+	}
+
+	for(int i=0;i<m_ranks;i++){
+		if(size(i)!=0){
+			return false;
+		}
+	}
+	return true;
+}
+
+/** Attempt to flush any buffer
+ * Returns 0 if all buffers are empty
+ * Returns 1 if a buffer was flushed
+ *
+ * This method does not flush more than one buffer at once
+ *
+ * \author Sébastien Boisvert
+ */
+int BufferedData::flushAll(int tag,RingAllocator*outboxAllocator,StaticVector*outbox,int rank){
+	if(isEmpty()){
+		return 0;
+	}
+	int flushed=0;
+	for(int i=0;i<m_ranks;i++){
+		if(flush(i,0,tag,outboxAllocator,outbox,rank,true)){
+			flushed++;
+			return flushed;
+		}
+		#ifdef ASSERT
+		assert(size(i)==0);
+		#endif
+	}
+	return flushed;
+}
+
+bool BufferedData::flush(int destination,int period,int tag,RingAllocator*outboxAllocator,StaticVector*outbox,int rank,bool force){
+	#ifdef ASSERT
+	if(!force){
+		assert(period!=0);
+	}
+	#endif
+
+	int threshold=0;
+	if(!force){
+		threshold=(m_capacity/period)*period;
+	}
+
+	#ifdef ASSERT
+	assert(threshold<=m_capacity);
+	#endif
+
+	int amount=size(destination);
+	if(!force && amount<threshold){
+		return false;
+	}
+	if(amount==0){
+		return false;
+	}
+	#ifdef ASSERT
+	assert(amount>0);
+	if(!force && amount>threshold){
+		cout<<"Threshold is exceeded "<<amount<<" & "<<threshold<<" tag="<<tag<<endl;
+	}
+	assert(force || amount<=threshold);
+	#endif
+
+	MessageUnit*message=(MessageUnit*)outboxAllocator->allocate(amount*sizeof(MessageUnit));
+	for(int i=0;i<amount;i++){
+		message[i]=getAt(destination,i);
+	}
+	Message aMessage(message,amount,destination,tag,rank);
+	outbox->push_back(aMessage);
+	m_flushedMessages++;
+	reset(destination);
+	return true;
+}
+
+bool BufferedData::needsFlushing(int destination,int period){
+	int threshold=(m_capacity/period)*period;
+	int amount=size(destination);
+	return amount>=threshold;
+}
+
+void BufferedData::showStatistics(int rank){
+	double ratio=100.0*m_flushedMessages;
+
+	if(m_pushedMessages!=0){
+		ratio/=m_pushedMessages;
+	}
+
+	cout<<"Rank "<<rank<<" : VirtualCommunicator (service provided by BufferedData): "<<m_pushedMessages;
+	cout<<" virtual messages generated "<<m_flushedMessages;
+	cout<<" real messages ("<<ratio<<"%)"<<endl;
+}
diff --git a/RayPlatform/communication/BufferedData.h b/RayPlatform/communication/BufferedData.h
new file mode 100644
index 0000000..f872c9e
--- /dev/null
+++ b/RayPlatform/communication/BufferedData.h
@@ -0,0 +1,103 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _BufferedData
+#define _BufferedData
+
+#include <stdint.h>
+#include <memory/MyAllocator.h>
+#include <structures/StaticVector.h>
+#include <memory/RingAllocator.h>
+
+/**
+ *  This class accumulates messages and flush them when the threshold is reached.
+ *
+ *  Messages are added in a periodic manner, and 4096 (-) something is the _real_ threshold.
+ *  Currently, MAXIMUM_MESSAGE_SIZE_IN_BYTES is 4000. Therefore, it is assumed that 96 bytes 
+ *  is an upper bound for the required space for a message's enveloppe.
+ *
+ *  for instance, if messages are of size 3 and the MAX_SIZE is 10,
+ *  then you want the threshold to be 9, that is 10/3*3 because else
+ *  at 9 it won't get flushed, and the next thing you know is that you are at 12,
+ *  this is above the threshold and the RingAllocator does not allow that.
+ * \author Sébastien Boisvert
+ */
+class BufferedData{
+	int m_count;
+	int m_period;
+	uint64_t m_flushedMessages;
+	uint64_t m_pushedMessages;
+	char m_type[100];
+	int*m_sizes;
+	int m_ranks;
+	bool m_show;
+
+	// the capacity is measured in uint64_t
+	int m_capacity;
+	MessageUnit*m_data;
+public:
+	/**
+ *	the is numberOfRanks MPI ranks, and messages have a capacity of capacity.
+ *
+	 the capacity is measured in uint64_t
+ */
+	void constructor(int numberOfRanks,int capacity,const char*type,bool show,int period);
+/*
+ * Get the number of appended elements for MPI rank i
+ */
+	int size(int i)const;
+/**
+ * Get the element j to send to MPI rank i
+ */
+	MessageUnit getAt(int i,int j);
+/**
+ * add an element to send to MPI rank i.
+ */
+	void addAt(int i,MessageUnit k);
+/**
+ * Clear output buffer for MPI rank i
+ */
+	void reset(int i);
+
+	/**
+ * return true if flushed something 
+ *  The result is mainly utilized to wait for a reply to regulate the communication in order 
+ *  to not exaust resources such as the RingAllocator.
+ * */
+	bool flush(int destination,int period,int tag,RingAllocator*outboxAllocator,StaticVector*outbox,int rank,bool force);
+
+	/**
+ *		returns the number of flushed devices.
+ *		TODO: this should be called flushAnyNonEmptyBuffer
+ */
+	int flushAll(int tag,RingAllocator*outboxAllocator,StaticVector*outbox,int rank);
+	bool isEmpty()const;
+	void clear();
+
+/*
+ * Returns true if any buffer is full.
+ */
+	bool needsFlushing(int destination,int period);
+	void showStatistics(int rank);
+};
+
+#endif
+
diff --git a/RayPlatform/communication/Message.cpp b/RayPlatform/communication/Message.cpp
new file mode 100644
index 0000000..a5eb27c
--- /dev/null
+++ b/RayPlatform/communication/Message.cpp
@@ -0,0 +1,85 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <communication/Message.h>
+#include <iostream>
+#include <communication/mpi_tags.h>
+using namespace std;
+
+/** buffer must be allocated or else it will CORE DUMP. */
+Message::Message(MessageUnit*b,int c,Rank dest,MessageTag tag,Rank source){
+	m_buffer=b;
+	m_count=c;
+	m_destination=dest;
+	m_tag=tag;
+	m_source=source;
+}
+
+MessageUnit*Message::getBuffer(){
+	return m_buffer;
+}
+
+int Message::getCount(){
+	return m_count;
+}
+
+Rank Message::getDestination(){
+	return m_destination;
+}
+
+MessageTag Message::getTag(){
+	return m_tag;
+}
+
+Message::Message(){}
+
+int Message::getSource(){
+	return m_source;
+}
+
+void Message::print(){
+	uint8_t shortTag=getTag();
+
+	cout<<"Source: "<<getSource()<<" Destination: "<<getDestination()<<" Tag: "<<MESSAGE_TAGS[shortTag]<<" Count: "<<getCount();
+	if(m_count > 0){
+		cout<<" Overlay: "<<hex<<m_buffer[0]<<dec;
+	}
+}
+
+void Message::setBuffer(MessageUnit*buffer){
+	m_buffer = buffer;
+}
+
+void Message::setTag(MessageTag tag){
+	m_tag=tag;
+}
+
+void Message::setCount(int count){
+	m_count=count;
+}
+
+void Message::setSource(Rank source){
+	m_source=source;
+}
+
+void Message::setDestination(Rank destination){
+	m_destination=destination;
+}
diff --git a/RayPlatform/communication/Message.h b/RayPlatform/communication/Message.h
new file mode 100644
index 0000000..71836eb
--- /dev/null
+++ b/RayPlatform/communication/Message.h
@@ -0,0 +1,92 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _Message_H
+#define _Message_H
+
+#include <stdint.h>
+#include <core/types.h>
+
+/**
+ * In Ray, every message is a Message.
+ * the inbox and the outbox are arrays of Message's
+ * All the code in Ray utilise Message to communicate information.
+ * MPI_Datatype is always MPI_UNSIGNED_LONG_LONG
+ * m_count is >=0 and <= MAXIMUM_MESSAGE_SIZE_IN_BYTES/sizeof(uint64_t)
+ *  (default is 4000/8 = 500 ).
+ * \author Sébastien Boisvert
+ */
+class Message{
+	/** the message body, contains data
+ * 	if NULL, m_count must be 0 */
+	MessageUnit*m_buffer;
+
+	/** the number of uint64_t that the m_buffer contains 
+ * 	can be 0 regardless of m_buffer value
+ * 	*/
+	int m_count;
+
+	/** the Message-passing interface rank destination 
+ * 	Must be >=0 and <= MPI_Comm_size()-1 */
+	Rank m_destination;
+
+	/**
+ * 	Ray message-passing interface message tags are named RAY_MPI_TAG_<something>
+ * 	see mpi_tag_macros.h 
+ */
+	MessageTag m_tag;
+
+	/** the message-passing interface rank source 
+ * 	Must be >=0 and <= MPI_Comm_size()-1 */
+	Rank m_source;
+public:
+	Message();
+	Message(MessageUnit*b,int c,Rank dest,MessageTag tag,Rank source);
+	MessageUnit*getBuffer();
+	int getCount();
+/**
+ * Returns the destination MPI rank
+ */
+	Rank getDestination();
+
+/**
+ * Returns the message tag (RAY_MPI_TAG_something)
+ */
+	MessageTag getTag();
+/**
+ * Gets the source MPI rank
+ */
+	Rank getSource();
+
+	void print();
+
+	void setBuffer(MessageUnit*buffer);
+
+	void setTag(MessageTag tag);
+
+	void setSource(Rank source);
+
+	void setDestination(Rank destination);
+
+	void setCount(int count);
+};
+
+#endif
diff --git a/RayPlatform/communication/MessageRouter.cpp b/RayPlatform/communication/MessageRouter.cpp
new file mode 100644
index 0000000..907109a
--- /dev/null
+++ b/RayPlatform/communication/MessageRouter.cpp
@@ -0,0 +1,462 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+//#define CONFIG_ROUTING_VERBOSITY
+
+/**
+ * \brief Message router implementation
+ *
+ * \author Sébastien Boisvert 2011-11-04
+ * \reviewedBy Elénie Godzaridis 2011-11-05
+*/
+
+#include <communication/MessageRouter.h>
+#include <string.h> /* for memcpy */
+#include <assert.h>
+#include <core/OperatingSystem.h>
+#include <core/ComputeCore.h>
+#include <time.h> /* for time */
+using namespace std;
+
+/* 
+ * According to the MPI standard, MPI_TAG_UB is >= 32767 (2^15-1) 
+ * Therefore, the tag must be >=0 and <= 32767 
+ * In most applications, there will be not that much tag
+ * values.
+ * 2^14 = 16384
+ * So that MPI tag in applications using RayPlatform can be
+ * from 0 to 16383.
+ * Internally, RayPlatform adds 16384 to the application tag.
+ * A routing tag is >= 16384 and the corresponding real tag is
+ * tag - 16384.
+ */
+#define __ROUTING_TAG_BASE 16384 
+
+#define __ROUTING_SOURCE 0
+#define __ROUTING_DESTINATION 1
+#define __ROUTING_OFFSET(count) (count-1)
+
+/*
+#define ASSERT
+*/
+
+/**
+ * route outcoming messages
+ */
+void MessageRouter::routeOutcomingMessages(){
+	int numberOfMessages=m_outbox->size();
+
+	if(numberOfMessages==0)
+		return;
+
+	for(int i=0;i<numberOfMessages;i++){
+		Message*aMessage=m_outbox->at(i);
+
+		MessageTag communicationTag=aMessage->getTag();
+
+		#ifdef CONFIG_ROUTING_VERBOSITY
+		uint8_t printableTag=communicationTag;
+		cout<<"[routeOutcomingMessages] tag= "<<MESSAGE_TAGS[printableTag]<<" value="<<communicationTag<<endl;
+		#endif
+
+		// - first, the message may have been already routed when it was received (also
+		// in a routed version). In this case, nothing must be done.
+		if(isRoutingTag(communicationTag)){
+			#ifdef CONFIG_ROUTING_VERBOSITY
+			cout<<"["<<__func__<<"] Message has already a routing tag."<<endl;
+			#endif
+			continue;
+		}
+
+		// at this point, the message has no routing information yet.
+		Rank trueSource=aMessage->getSource();
+		Rank trueDestination=aMessage->getDestination();
+
+		// if it is reachable, no further routing is required
+		if(m_graph.isConnected(trueSource,trueDestination)){
+
+			#ifdef CONFIG_ROUTING_VERBOSITY
+			cout<<"["<<__func__<<"] Rank "<<trueSource<<" can reach "<<trueDestination<<" without routing"<<endl;
+			#endif
+
+			continue;
+		}
+	
+		// re-route the message by re-writing the tag
+		MessageTag routingTag=getRoutingTag(communicationTag);
+		aMessage->setTag(routingTag);
+
+		MessageUnit*buffer=aMessage->getBuffer();
+
+		// we need space for routing information
+		// also, if this is a control message sent to all, we need
+		// to allocate new buffers.
+		// There is no problem at rewritting buffers that have non-null buffers,
+		// but it is useless if the buffer is used once.
+		// So numberOfMessages==m_size is just an optimization.
+		if(aMessage->getBuffer()==NULL||numberOfMessages==m_size){
+
+			#ifdef ASSERT
+			assert(aMessage->getCount()==0||numberOfMessages==m_size);
+			#endif
+
+			buffer=(MessageUnit*)m_outboxAllocator->allocate(MAXIMUM_MESSAGE_SIZE_IN_BYTES);
+
+			#ifdef ASSERT
+			assert(buffer!=NULL);
+			#endif
+
+			// copy the old stuff too
+			if(aMessage->getBuffer()!=NULL)
+				memcpy(buffer,aMessage->getBuffer(),aMessage->getCount()*sizeof(MessageUnit));
+
+			aMessage->setBuffer(buffer);
+		}
+
+		// routing information is stored in 64 bits
+		int newCount=aMessage->getCount()+1;
+		aMessage->setCount(newCount);
+		
+		#ifdef ASSERT
+		assert(buffer!=NULL);
+		#endif
+
+		setSourceInBuffer(buffer,newCount,trueSource);
+		setDestinationInBuffer(buffer,newCount,trueDestination);
+
+		#ifdef ASSERT
+		assert(getSourceFromBuffer(aMessage->getBuffer(),aMessage->getCount())==trueSource);
+		assert(getDestinationFromBuffer(aMessage->getBuffer(),aMessage->getCount())==trueDestination);
+		#endif
+
+		Rank nextRank=m_graph.getNextRankInRoute(trueSource,trueDestination,m_rank);
+		aMessage->setDestination(nextRank);
+
+		#ifdef CONFIG_ROUTING_VERBOSITY
+		cout<<"["<<__func__<<"] relayed message, trueSource="<<trueSource<<" trueDestination="<<trueDestination<<" to intermediateSource "<<nextRank<<endl;
+		#endif
+	}
+
+	// check that all messages are routable
+	#ifdef ASSERT
+	for(int i=0;i<numberOfMessages;i++){
+		Message*aMessage=m_outbox->at(i);
+		if(!m_graph.isConnected(aMessage->getSource(),aMessage->getDestination()))
+			cout<<aMessage->getSource()<<" and "<<aMessage->getDestination()<<" are not connected !"<<endl;
+		assert(m_graph.isConnected(aMessage->getSource(),aMessage->getDestination()));
+	}
+	#endif
+}
+
+/**
+ * route incoming messages 
+ * \returns true if rerouted something.
+ */
+bool MessageRouter::routeIncomingMessages(){
+	int numberOfMessages=m_inbox->size();
+
+	#ifdef CONFIG_ROUTING_VERBOSITY
+	cout<<"["<<__func__<<"] inbox.size= "<<numberOfMessages<<endl;
+	#endif
+
+	// we have no message
+	if(numberOfMessages==0)
+		return false;
+
+	// otherwise, we have exactly one precious message.
+	
+	Message*aMessage=m_inbox->at(0);
+	MessageTag tag=aMessage->getTag();
+	MessageUnit*buffer=aMessage->getBuffer();
+	int count=aMessage->getCount();
+
+	#ifdef CONFIG_ROUTING_VERBOSITY
+	uint8_t printableTag=tag;
+	cout<<"[routeIncomingMessages] tag= "<<MESSAGE_TAGS[printableTag]<<" value="<<tag<<endl;
+	#endif
+
+	// if the message has no routing tag, then we can safely receive it as is
+	if(!isRoutingTag(tag)){
+		// nothing to do
+		#ifdef CONFIG_ROUTING_VERBOSITY
+		cout<<"["<<__func__<<"] message has no routing tag, nothing to do"<<endl;
+		#endif
+
+		return false;
+	}
+
+	Rank trueSource=getSourceFromBuffer(buffer,count);
+	Rank trueDestination=getDestinationFromBuffer(buffer,count);
+
+	// this is the final destination
+	// we have received the message
+	// we need to restore the original information now.
+	if(trueDestination==m_rank){
+		#ifdef CONFIG_ROUTING_VERBOSITY
+		cout<<"["<<__func__<<"] message has reached destination, must strip routing information"<<endl;
+		#endif
+
+		// we must update the original source and original tag
+		aMessage->setSource(trueSource);
+		
+		// the original destination is already OK
+		#ifdef ASSERT
+		assert(aMessage->getDestination()==m_rank);
+		#endif
+
+		MessageTag trueTag=getMessageTagFromRoutingTag(tag);
+		aMessage->setTag(trueTag);
+
+		#ifdef CONFIG_ROUTING_VERBOSITY
+		cout<<"[routeIncomingMessages] real tag= "<<trueTag<<endl;
+		#endif
+
+		// remove the routing stuff
+		int newCount=aMessage->getCount()-1;
+
+		#ifdef ASSERT
+		assert(newCount>=0);
+		#endif
+
+		aMessage->setCount(newCount);
+
+		// set the buffer to NULL if there is no data
+		if(newCount==0)
+			aMessage->setBuffer(NULL);
+
+		return false;
+	}
+
+	#ifdef ASSERT
+	assert(m_rank!=trueDestination);
+	#endif
+
+	// at this point, we know that we need to forward
+	// the message to another peer
+	Rank nextRank=m_graph.getNextRankInRoute(trueSource,trueDestination,m_rank);
+
+	#ifdef CONFIG_ROUTING_VERBOSITY
+	cout<<"["<<__func__<<"] message has been sent to the next one, trueSource="<<trueSource<<" trueDestination= "<<trueDestination;
+	cout<<" Previous= "<<aMessage->getSource()<<" Current= "<<m_rank<<" Next= "<<nextRank<<endl;
+	#endif
+		
+	// we forward the message
+	relayMessage(aMessage,nextRank);
+
+	// propagate the information about routing
+	return true;
+}
+
+/**
+ * forward a message to follow a route
+ */
+void MessageRouter::relayMessage(Message*message,Rank destination){
+	
+	int count=message->getCount();
+
+	// routed messages always have a payload
+	#ifdef ASSERT
+	assert(count>=1);
+	#endif
+
+	MessageUnit*outgoingMessage=(MessageUnit*)m_outboxAllocator->allocate(MAXIMUM_MESSAGE_SIZE_IN_BYTES);
+
+	// copy the data into the new buffer
+	memcpy(outgoingMessage,message->getBuffer(),count*sizeof(MessageUnit));
+	message->setBuffer(outgoingMessage);
+
+	#ifdef CONFIG_ROUTING_VERBOSITY
+	cout<<"[relayMessage] TrueSource="<<getSourceFromBuffer(message->getBuffer(),message->getCount());
+	cout<<" TrueDestination="<<getDestinationFromBuffer(message->getBuffer(),message->getCount());
+	cout<<" RelaySource="<<m_rank<<" RelayDestination="<<destination<<endl;
+	#endif
+
+	// re-route the message
+	message->setSource(m_rank);
+	message->setDestination(destination);
+
+	#ifdef ASSERT
+	assert(m_graph.isConnected(m_rank,destination));
+	#endif
+
+	m_outbox->push_back(*message);
+}
+
+
+/**
+ * a tag is a routing tag is its routing bit is set to 1
+ */
+bool MessageRouter::isEnabled(){
+	return m_enabled;
+}
+
+MessageRouter::MessageRouter(){
+	m_enabled=false;
+}
+
+void MessageRouter::enable(StaticVector*inbox,StaticVector*outbox,RingAllocator*outboxAllocator,Rank rank,
+	string prefix,int numberOfRanks,string type,int degree){
+
+	m_graph.buildGraph(numberOfRanks,type,rank==MASTER_RANK,degree);
+
+	m_size=numberOfRanks;
+
+	cout<<endl;
+
+	cout<<"[MessageRouter] Enabled message routing"<<endl;
+
+	m_inbox=inbox;
+	m_outbox=outbox;
+	m_outboxAllocator=outboxAllocator;
+	m_rank=rank;
+	m_enabled=true;
+
+	if(m_rank==MASTER_RANK)
+		m_graph.writeFiles(prefix);
+
+	m_deletionTime=0;
+}
+
+bool MessageRouter::hasCompletedRelayEvents(){
+
+	int duration=16;
+
+	if(m_deletionTime==0){
+		m_deletionTime=time(NULL);
+		cout<<"[MessageRouter] Rank "<<m_rank<<" will die in "<<duration<<" seconds,";
+		cout<<" will not route anything after that point."<<endl;
+	}
+
+	time_t now=time(NULL);
+
+	return now >= (m_deletionTime+duration);
+}
+
+/*
+ * just add a magic number
+ */
+MessageTag MessageRouter::getRoutingTag(MessageTag tag){
+	#ifdef ASSERT
+	assert(tag>=0);
+	assert(tag<32768);
+	#endif
+
+	return tag+__ROUTING_TAG_BASE;
+}
+
+ConnectionGraph*MessageRouter::getGraph(){
+	return &m_graph;
+}
+
+bool MessageRouter::isRoutingTag(MessageTag tag){
+	return tag>=__ROUTING_TAG_BASE;
+}
+
+MessageTag MessageRouter::getMessageTagFromRoutingTag(MessageTag tag){
+
+	#ifdef ASSERT
+	assert(isRoutingTag(tag));
+	assert(tag>=__ROUTING_TAG_BASE);
+	#endif
+
+	tag-=__ROUTING_TAG_BASE;
+
+	#ifdef ASSERT
+	assert(tag>=0);
+	#endif
+
+	return tag;
+}
+
+Rank MessageRouter::getSourceFromBuffer(MessageUnit*buffer,int count){
+	#ifdef ASSERT
+	assert(count>=1);
+	assert(buffer!=NULL);
+	#endif
+
+	uint32_t*routingInformation=(uint32_t*)(buffer+__ROUTING_OFFSET(count));
+
+	Rank rank=routingInformation[__ROUTING_SOURCE];
+
+	#ifdef ASSERT
+	assert(rank>=0);
+	assert(rank<m_size);
+	#endif
+
+	return rank;
+}
+
+Rank MessageRouter::getDestinationFromBuffer(MessageUnit*buffer,int count){
+
+	#ifdef ASSERT
+	assert(count>=1);
+	assert(buffer!=NULL);
+	#endif
+
+	uint32_t*routingInformation=(uint32_t*)(buffer+__ROUTING_OFFSET(count));
+
+	Rank rank=routingInformation[__ROUTING_DESTINATION];
+
+	#ifdef ASSERT
+	assert(rank>=0);
+	assert(rank<m_size);
+	#endif
+
+	return rank;
+}
+
+void MessageRouter::setSourceInBuffer(MessageUnit*buffer,int count,Rank source){
+
+	#ifdef CONFIG_ROUTING_VERBOSITY
+	cout<<"[setSourceInBuffer] buffer="<<buffer<<" source="<<source<<endl;
+	#endif
+
+	#ifdef ASSERT
+	assert(count>=1);
+	assert(buffer!=NULL);
+	assert(source>=0);
+	assert(source<m_size);
+	#endif
+
+	uint32_t*routingInformation=(uint32_t*)(buffer+__ROUTING_OFFSET(count));
+
+	routingInformation[__ROUTING_SOURCE]=source;
+}
+
+void MessageRouter::setDestinationInBuffer(MessageUnit*buffer,int count,Rank destination){
+
+	#ifdef CONFIG_ROUTING_VERBOSITY
+	cout<<"[setDestinationInBuffer] buffer="<<buffer<<" destination="<<destination<<endl;
+	#endif
+
+	#ifdef ASSERT
+	assert(count>=1);
+	assert(buffer!=NULL);
+	assert(destination>=0);
+	assert(destination<m_size);
+	#endif
+
+	uint32_t*routingInformation=(uint32_t*)(buffer+__ROUTING_OFFSET(count));
+
+	routingInformation[__ROUTING_DESTINATION]=destination;
+}
+
+
diff --git a/RayPlatform/communication/MessageRouter.h b/RayPlatform/communication/MessageRouter.h
new file mode 100644
index 0000000..43633cd
--- /dev/null
+++ b/RayPlatform/communication/MessageRouter.h
@@ -0,0 +1,132 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _MessageRouter_h
+#define _MessageRouter_h
+
+#include <memory/RingAllocator.h>
+#include <structures/StaticVector.h>
+#include <communication/Message.h>
+#include <routing/ConnectionGraph.h>
+#include <core/types.h>
+
+class ComputeCore;
+
+#include <string>
+#include <map>
+#include <vector>
+#include <time.h> /* for time() */
+using namespace std;
+
+/**
+ * \author Sébastien Boisvert 2011-11-04
+ * \reviewedBy Elénie Godzaridis 2011-11-05
+ *
+ * the MessageRouter makes communication more efficient.
+ *
+ */
+class MessageRouter {
+
+/** the extra ticks after the computation has completed. **/
+	time_t m_deletionTime;
+
+
+/**  the connection graph */
+	ConnectionGraph m_graph;
+
+/**
+ * Is the router activated at all ?
+ */
+	bool m_enabled;
+
+/**
+ * The message inbox
+ */
+	StaticVector*m_inbox;
+
+/**
+ * The message outbox
+ */
+	StaticVector*m_outbox;
+
+/**
+ * The outbox buffer allocator
+ */
+	RingAllocator*m_outboxAllocator;
+
+/**
+ * The identifier of the current rank
+ */
+	Rank m_rank;
+
+/**
+ * The number of ranks
+ */
+	int m_size;
+
+	void relayMessage(Message*message,Rank destination);
+
+	bool isRoutingTag(MessageTag tag);
+
+	MessageTag getMessageTagFromRoutingTag(MessageTag tag);
+	Rank getSourceFromBuffer(MessageUnit*buffer,int count);
+	Rank getDestinationFromBuffer(MessageUnit*buffer,int count);
+	MessageTag getRoutingTag(MessageTag tag);
+	void setSourceInBuffer(MessageUnit*buffer,int count,Rank source);
+	void setDestinationInBuffer(MessageUnit*buffer,int count,Rank destination);
+
+public:
+	MessageRouter();
+
+/**
+ * Callback method to call before sending messages in the outbox onto the network
+ */
+	void routeOutcomingMessages();
+
+/**
+ * Callback method to call after receiving messages from the network into the inbox
+ */
+	bool routeIncomingMessages();
+
+	bool isEnabled();
+
+/**
+ * Enable the router
+ * This could be a constructor.
+ */
+	void enable(StaticVector*inbox,StaticVector*outbox,RingAllocator*outboxAllocator,Rank rank,
+string prefix,int numberOfRanks,string type,int degree);
+
+/**
+ * Check if relayed messages have completed their transit.
+ * This is required for the messages sent at the end
+ * of the computation because we need ranks to shut down 
+ * after they have relayed messages for which they act as
+ * relay in the routing table.
+ *
+ * This is only called once the loop is dead, that is m_alive= false;
+ */
+	bool hasCompletedRelayEvents();
+
+	ConnectionGraph*getGraph();
+};
+
+#endif /* _MessageRouter_h */
diff --git a/RayPlatform/communication/MessagesHandler.cpp b/RayPlatform/communication/MessagesHandler.cpp
new file mode 100644
index 0000000..79184d0
--- /dev/null
+++ b/RayPlatform/communication/MessagesHandler.cpp
@@ -0,0 +1,890 @@
+/*
+ 	RayPlatform
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <communication/MessagesHandler.h>
+
+/* for decoding message tags */
+#include <communication/MessageRouter.h> 
+#include <memory/allocator.h>
+#include <core/OperatingSystem.h>
+#include <core/ComputeCore.h>
+
+#include <fstream>
+#include <assert.h>
+#include <iostream>
+#include <sstream>
+#include <string.h>
+using namespace std;
+
+// #define COMMUNICATION_IS_VERBOSE
+
+#define __NOT_SET -1
+
+/**
+ * TODO Instead of a true/false state, increase and decrease requests
+ * using a particular buffer. Otherwise, there may be a problem when 
+ * a buffer is re-used several times for many requests.
+ */
+void MessagesHandler::checkDirtyBuffer(RingAllocator*outboxBufferAllocator,int index){
+
+	#ifdef ASSERT
+	assert(m_numberOfDirtyBuffers>0);
+	#endif
+
+	if(m_dirtyBuffers[index].m_buffer==NULL)// this entry is empty...
+		return;
+
+	// check the buffer and free it if it is finished.
+	MPI_Status status;
+	MPI_Request*request=&(m_dirtyBuffers[index].m_messageRequest);
+
+	int flag=0;
+
+	MPI_Test(request,&flag,&status);
+
+	if(!flag)// this slot is not ready
+		return;
+
+	#ifdef ASSERT
+	assert( flag );
+	#endif /* ASSERT */
+
+	void*buffer=m_dirtyBuffers[index].m_buffer;
+	outboxBufferAllocator->salvageBuffer(buffer);
+	m_numberOfDirtyBuffers--;
+
+	#ifdef COMMUNICATION_IS_VERBOSE
+	cout<<"From checkDirtyBuffer flag= "<<flag<<endl;
+	#endif /* COMMUNICATION_IS_VERBOSE */
+
+	#ifdef ASSERT
+	assert(*request == MPI_REQUEST_NULL);
+	#endif /* ASSERT */
+
+	m_dirtyBuffers[index].m_buffer=NULL;
+}
+
+void MessagesHandler::cleanDirtyBuffers(RingAllocator*outboxBufferAllocator){
+
+/**
+ * don't do any linear sweep if we still have plenty of free cells
+ */
+	if(m_numberOfDirtyBuffers<m_minimumNumberOfDirtyBuffersForSweep)
+		return;
+
+	#ifdef ASSERT
+	assert(m_numberOfDirtyBuffers>0);
+	#endif
+
+	m_linearSweeps++;
+
+	// update the dirty buffer list.
+	for(int i=0;i<m_dirtyBufferSlots;i++){
+		if(m_numberOfDirtyBuffers==0)
+			return;
+
+		checkDirtyBuffer(outboxBufferAllocator,i);
+	}
+
+	if(m_numberOfDirtyBuffers>=m_minimumNumberOfDirtyBuffersForWarning){
+		cout<<"[MessagesHandler] Warning: dirty buffers are still dirty after linear sweep."<<endl;
+		printDirtyBuffers();
+	}
+}
+
+void MessagesHandler::printDirtyBuffers(){
+
+	cout<<"[MessagesHandler] Dirty buffers: "<<m_numberOfDirtyBuffers<<"/";
+	cout<<m_dirtyBufferSlots<<endl;
+
+	for(int i=0;i<m_dirtyBufferSlots;i++){
+		cout<<"DirtyBuffer # "<<i<<"    State: ";
+		if(m_dirtyBuffers[i].m_buffer==NULL){
+			cout<<"Available"<<endl;
+		}else{
+			cout<<"Dirty"<<endl;
+
+			MessageTag tag=m_dirtyBuffers[i].m_messageTag;
+			Rank destination=m_dirtyBuffers[i].m_destination;
+			Rank routingSource=m_rank;
+			Rank routingDestination=destination;
+
+			bool isRoutingTagValue=false;
+
+/* TODO we don't have easy access to this information */
+#if 0
+			RoutingTag routingTag=tag;
+
+			if(isRoutingTag(tag)){
+				tag=getMessageTagFromRoutingTag(routingTag);
+				routingSource=getSourceFromRoutingTag(routingTag);
+				routingDestination=getDestinationFromRoutingTag(routingTag);
+
+				isRoutingTagValue=true;
+			}
+#endif
+
+			uint8_t index=tag;
+			cout<<" MessageTag: "<<MESSAGE_TAGS[index]<<" ("<<(int)index<<") ";
+			if(index<tag){
+				cout<<"[this is a routing tag]"<<endl;
+			}
+			cout<<" Source: "<<m_rank<<endl;
+			cout<<" Destination: "<<destination<<endl;
+
+			if(isRoutingTagValue){
+				cout<<" RoutingSource: "<<routingSource<<endl;
+				cout<<" RoutingDestination: "<<routingDestination<<endl;
+			}
+		}
+	}
+}
+
+void MessagesHandler::initializeDirtyBuffers(RingAllocator*outboxBufferAllocator){
+
+	m_dirtyBufferSlots=outboxBufferAllocator->getNumberOfBuffers();
+
+	m_dirtyBuffers=(DirtyBuffer*)__Malloc(m_dirtyBufferSlots*sizeof(DirtyBuffer),
+		"m_dirtyBuffers",false);
+
+	for(int i=0;i<m_dirtyBufferSlots;i++){
+		m_dirtyBuffers[i].m_buffer=NULL;
+	}
+
+	// configure the real-time sweeper.
+
+	m_minimumNumberOfDirtyBuffersForSweep=m_dirtyBufferSlots/4;
+	m_minimumNumberOfDirtyBuffersForWarning=m_dirtyBufferSlots/2;
+
+}
+
+/*
+ * send messages,
+ *
+ * Regarding m_dirtyBufferSlots:
+ *
+ * this is the maximum number of dirty buffers
+ * it should be at least the number of allocated
+ * buffer in a RayPlatform virtual machine tick.
+ *
+ * For very large jobs, this might need to be increased
+ * in order to avoid the situation in which
+ * all the buffer for the outbox are dirty/used.
+ */
+void MessagesHandler::sendMessages(StaticVector*outbox,RingAllocator*outboxBufferAllocator){
+
+	// initialize the dirty buffer counters
+	// this is done only once
+	if(m_dirtyBuffers==NULL)
+		initializeDirtyBuffers(outboxBufferAllocator);
+
+	cleanDirtyBuffers(outboxBufferAllocator);
+
+	// send messages.
+	for(int i=0;i<(int)outbox->size();i++){
+		Message*aMessage=((*outbox)[i]);
+		Rank destination=aMessage->getDestination();
+		void*buffer=aMessage->getBuffer();
+		int count=aMessage->getCount();
+		MessageTag tag=aMessage->getTag();
+
+		#ifdef ASSERT
+		assert(destination>=0);
+		if(destination>=m_size){
+			cout<<"Tag="<<tag<<" Destination="<<destination<<endl;
+		}
+		assert(destination<m_size);
+		assert(!(buffer==NULL && count>0));
+
+		// this assertion is invalid when using checksum calculation.
+		//assert(count<=(int)(MAXIMUM_MESSAGE_SIZE_IN_BYTES/sizeof(MessageUnit)));
+		#endif /* ASSERT */
+
+		MPI_Request dummyRequest;
+
+		MPI_Request*request=&dummyRequest;
+
+		int handle=-1;
+
+		/* compute the handle, this is O(1) */
+		if(buffer!=NULL)
+			handle=outboxBufferAllocator->getBufferHandle(buffer);
+
+		bool mustRegister=false;
+
+		// this buffer is not registered.
+		if(handle >=0 && m_dirtyBuffers[handle].m_buffer==NULL)
+			mustRegister=true;
+
+		/* register the buffer for processing */
+		if(mustRegister){
+			#ifdef ASSERT
+			assert(m_dirtyBuffers[handle].m_buffer==NULL);
+			#endif
+
+			m_dirtyBuffers[handle].m_buffer=buffer;
+			m_dirtyBuffers[handle].m_destination=destination;
+			m_dirtyBuffers[handle].m_messageTag=tag;
+
+			#ifdef ASSERT
+			assert(m_dirtyBuffers[handle].m_buffer!=NULL);
+			#endif
+
+			request=&(m_dirtyBuffers[handle].m_messageRequest);
+
+			/* this is O(1) */
+			outboxBufferAllocator->markBufferAsDirty(buffer);
+
+			m_numberOfDirtyBuffers++;
+
+			// update the maximum number of dirty buffers
+			// observed since the beginning.
+			if(m_numberOfDirtyBuffers > m_maximumDirtyBuffers)
+				m_maximumDirtyBuffers=m_numberOfDirtyBuffers;
+		}
+
+		#ifdef ASSERT
+		assert(request!=NULL);
+		#endif
+
+		//  MPI_Isend
+		//      Synchronous nonblocking. 
+		MPI_Isend(buffer,count,m_datatype,destination,tag,MPI_COMM_WORLD,request);
+
+		// if the buffer is NULL, we free the request right now
+		// because we there is no buffer to protect.
+		if(!mustRegister){
+
+			#ifdef COMMUNICATION_IS_VERBOSE
+			cout<<" From sendMessages"<<endl;
+			#endif
+
+			MPI_Request_free(request);
+
+			#ifdef ASSERT
+			assert(*request==MPI_REQUEST_NULL);
+			#endif
+
+		}
+
+		// if the message was re-routed, we don't care
+		// we only fetch the tag for statistics
+		uint8_t shortTag=tag;
+
+		/** update statistics */
+		m_messageStatistics[destination*RAY_MPI_TAG_DUMMY+shortTag]++;
+
+		m_sentMessages++;
+	}
+
+	outbox->clear();
+}
+
+#ifdef CONFIG_COMM_PERSISTENT
+
+/*	
+ * receiveMessages is implemented as recommanded by Mr. George Bosilca from
+the University of Tennessee (via the Open-MPI mailing list)
+
+De: George Bosilca <bosilca@…>
+Reply-to: Open MPI Developers <devel@…>
+À: Open MPI Developers <devel@…>
+Sujet: Re: [OMPI devel] Simple program (103 lines) makes Open-1.4.3 hang
+Date: 2010-11-23 18:03:04
+
+If you know the max size of the receives I would take a different approach. 
+Post few persistent receives, and manage them in a circular buffer. 
+Instead of doing an MPI_Iprobe, use MPI_Test on the current head of your circular buffer. 
+Once you use the data related to the receive, just do an MPI_Start on your request.
+This approach will minimize the unexpected messages, and drain the connections faster. 
+Moreover, at the end it is very easy to MPI_Cancel all the receives not yet matched.
+
+ */
+void MessagesHandler::pumpMessageFromPersistentRing(StaticVector*inbox,RingAllocator*inboxAllocator){
+
+	/* persistent communication is not enabled by default */
+	int flag=0;
+	MPI_Status status;
+	MPI_Request*request=m_ring+m_head;
+	MPI_Test(request,&flag,&status);
+
+	if(flag){
+		// get the length of the message
+		// it is not necessary the same as the one posted with MPI_Recv_init
+		// that one was a lower bound
+		MessageTag  tag=status.MPI_TAG;
+		Rank source=status.MPI_SOURCE;
+
+		int count;
+		MPI_Get_count(&status,m_datatype,&count);
+		MessageUnit*filledBuffer=(MessageUnit*)m_buffers+m_head*MAXIMUM_MESSAGE_SIZE_IN_BYTES/sizeof(MessageUnit);
+
+		// copy it in a safe buffer
+		// internal buffers are all of length MAXIMUM_MESSAGE_SIZE_IN_BYTES
+		MessageUnit*incoming=(MessageUnit*)inboxAllocator->allocate(MAXIMUM_MESSAGE_SIZE_IN_BYTES);
+
+		memcpy(incoming,filledBuffer,count*sizeof(MessageUnit));
+
+		// the request can start again
+		MPI_Start(m_ring+m_head);
+	
+		// add the message in the internal inbox
+		// this inbox is not the real inbox
+		Message aMessage(incoming,count,m_rank,tag,source);
+
+		inbox->push_back(aMessage);
+	}
+
+	// advance the ring.
+	m_head++;
+
+	if(m_head == m_ringSize)
+		m_head = 0;
+}
+
+#endif /* CONFIG_COMM_PERSISTENT */
+
+void MessagesHandler::receiveMessages(StaticVector*inbox,RingAllocator*inboxAllocator){
+	#if defined CONFIG_COMM_IPROBE_ROUND_ROBIN
+
+// round-robin reception seems to avoid starvation 
+/** round robin with Iprobe will increase the latency because there will be a lot of calls to
+ MPI_Iprobe that yield no messages at all */
+
+	roundRobinReception(inbox,inboxAllocator);
+
+	#elif defined CONFIG_COMM_PERSISTENT
+
+	// use persistent communication
+	pumpMessageFromPersistentRing(inbox,inboxAllocator);
+
+	#elif defined CONFIG_COMM_IPROBE_ANY_SOURCE
+
+	// receive any message
+	// it is assumed that MPI is fair
+	// otherwise there may be some starvation
+
+	probeAndRead(MPI_ANY_SOURCE,MPI_ANY_TAG,inbox,inboxAllocator);
+
+	#elif defined CONFIG_COMM_IRECV_TESTANY
+
+	receiveMessages_irecv_testany(inbox,inboxAllocator);
+
+	#else
+
+	#error "No communication model is selected."
+
+	#endif
+}
+
+#ifdef CONFIG_COMM_IRECV_TESTANY
+
+/*
+ * Implementation of the communication layer using
+ * MPI_Irecv, MPI_Isend, and MPI_Testany
+ *
+ * According to Pavan Balaji (MPICH2) and Jeff Squyres (Open-MPI),
+ * this should produce the best performance.
+ */
+
+/**
+ * Starts a non-blocking reception
+ */
+void MessagesHandler::startNonBlockingReception(int handle){
+	
+	#ifdef ASSERT
+	assert(handle<m_numberOfNonBlockingReceives);
+	assert(handle>=0);
+	#endif /* ASSERT */
+
+	void*buffer=m_receptionBuffers+handle*m_bufferSize;
+
+	MPI_Request*request=m_requests+handle;
+
+	#ifdef ASSERT
+	assert(buffer!=NULL);
+	assert(request!=NULL);
+	#endif /* ASSERT */
+
+	MPI_Irecv(buffer,m_bufferSize/sizeof(MessageUnit),m_datatype,
+		MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,request);
+}
+
+void MessagesHandler::init_irecv_testany(RingAllocator*inboxAllocator){
+
+	m_bufferSize=inboxAllocator->getSize();
+	m_numberOfNonBlockingReceives=m_size+10;
+
+	m_requests=(MPI_Request*)__Malloc(sizeof(MPI_Request)*m_numberOfNonBlockingReceives,
+		"CONFIG_COMM_IRECV_TESTANY",false);
+	m_receptionBuffers=(uint8_t*)__Malloc(m_bufferSize*m_numberOfNonBlockingReceives,
+		"CONFIG_COMM_IRECV_TESTANY",false);
+	
+	#ifdef ASSERT
+	assert(m_requests!=NULL);
+	#endif
+
+	for(int i=0;i<m_numberOfNonBlockingReceives;i++)
+		startNonBlockingReception(i);
+}
+
+void MessagesHandler::destroy_irecv_testany(){
+
+	if(m_requests==NULL)
+		return;
+
+	for(int i=0;i<m_numberOfNonBlockingReceives;i++){
+		MPI_Cancel(m_requests+i);
+		MPI_Request_free(m_requests+i);
+	}
+
+	__Free(m_requests,"CONFIG_COMM_IRECV_TESTANY",false);
+	m_requests=NULL;
+	__Free(m_receptionBuffers,"CONFIG_COMM_IRECV_TESTANY",false);
+	m_receptionBuffers=NULL;
+
+}
+
+void MessagesHandler::receiveMessages_irecv_testany(StaticVector*inbox,RingAllocator*inboxAllocator){
+
+	if(m_requests==NULL)
+		init_irecv_testany(inboxAllocator);
+
+	int indexOfCompletedRequest=MPI_UNDEFINED;
+	int hasCompleted=0;
+	MPI_Status status;
+
+	#ifdef ASSERT
+	int returnValue=
+	#endif /* ASSERT */
+
+	MPI_Testany(m_numberOfNonBlockingReceives,m_requests,
+		&indexOfCompletedRequest,&hasCompleted,&status);
+
+	#ifdef ASSERT
+	assert(returnValue==MPI_SUCCESS);
+	#endif /* ASSERT */
+
+	if(hasCompleted==0)
+		return;
+
+	MPI_Datatype datatype=MPI_UNSIGNED_LONG_LONG;
+	MessageTag actualTag=status.MPI_TAG;
+	Rank actualSource=status.MPI_SOURCE;
+	int count=-1;
+	MPI_Get_count(&status,datatype,&count);
+
+	uint8_t*populatedBuffer=m_receptionBuffers+indexOfCompletedRequest*m_bufferSize;
+
+	#ifdef ASSERT
+	assert(count >= 0);
+	#endif
+
+	MessageUnit*incoming=NULL;
+	if(count > 0){
+		incoming=(MessageUnit*)inboxAllocator->allocate(count*sizeof(MessageUnit));
+		memcpy(incoming,populatedBuffer,count*sizeof(MessageUnit));
+	}
+
+	Message aMessage(incoming,count,m_rank,actualTag,actualSource);
+	inbox->push_back(aMessage);
+
+	#ifdef ASSERT
+	assert(aMessage.getDestination() == m_rank);
+	#endif
+
+	m_receivedMessages++;
+
+	startNonBlockingReception(indexOfCompletedRequest);
+}
+
+#endif /* CONFIG_COMM_IRECV_TESTANY */
+
+#ifdef CONFIG_COMM_IPROBE_ROUND_ROBIN
+
+void MessagesHandler::roundRobinReception(StaticVector*inbox,RingAllocator*inboxAllocator){
+
+	/* otherwise, we use MPI_Iprobe + MPI_Recv */
+	/* probe and read a message */
+
+	int operations=0;
+	while(operations<m_size){
+
+		probeAndRead(m_connections[m_currentRankIndexToTryToReceiveFrom],MPI_ANY_TAG,
+			inbox,inboxAllocator);
+
+		// advance the head
+		m_currentRankIndexToTryToReceiveFrom++;
+		if(m_currentRankIndexToTryToReceiveFrom==m_peers){
+			m_currentRankIndexToTryToReceiveFrom=0;
+		}
+
+		// increment operations
+		operations++;
+
+		// only 1 MPI_Iprobe is called for any source
+		#ifdef CONFIG_COMM_IPROBE_ANY_SOURCE
+		break;
+		#endif /* CONFIG_COMM_IPROBE_ANY_SOURCE */
+
+		#ifdef CONFIG_COMM_IPROBE_ROUND_ROBIN
+		#ifdef CONFIG_ONE_IPROBE_PER_TICK
+		break;
+		#endif /* CONFIG_ONE_IPROBE_PER_TICK */
+		#endif /* CONFIG_COMM_IPROBE_ROUND_ROBIN */
+
+
+		// we have read a message
+		if(inbox->size()>0){
+			break;
+		}
+	}
+
+	#ifdef COMMUNICATION_IS_VERBOSE
+	if(inbox->size() > 0){
+		cout<<"[RoundRobin] received a message from "<<m_currentRankIndexToTryToReceiveFrom<<endl;
+	}
+	#endif /* COMMUNICATION_IS_VERBOSE */
+
+}
+
+#endif /* CONFIG_COMM_IPROBE_ROUND_ROBIN */
+
+/* this code is utilised, 
+ * the code for persistent communication is not useful because
+ * round-robin policy and persistent communication are likely 
+ * not compatible because the number of persistent requests can be a limitation.
+ */
+void MessagesHandler::probeAndRead(Rank source,MessageTag tag,
+	StaticVector*inbox,RingAllocator*inboxAllocator){
+
+	// the code here will probe from rank source
+	// with MPI_Iprobe
+
+	#ifdef COMMUNICATION_IS_VERBOSE
+	cout<<"call to probeAndRead source="<<source<<""<<endl;
+	#endif /* COMMUNICATION_IS_VERBOSE */
+
+	int flag=0;
+	MPI_Status status;
+	MPI_Iprobe(source,tag,MPI_COMM_WORLD,&flag,&status);
+
+	// nothing to receive...
+	if(!flag)
+		return;
+
+	/* read at most one message */
+	MPI_Datatype datatype=MPI_UNSIGNED_LONG_LONG;
+	int actualTag=status.MPI_TAG;
+	Rank actualSource=status.MPI_SOURCE;
+	int count=-1;
+	MPI_Get_count(&status,datatype,&count);
+
+	#ifdef ASSERT
+	assert(count >= 0);
+	#endif
+
+	MessageUnit*incoming=NULL;
+	if(count > 0){
+		incoming=(MessageUnit*)inboxAllocator->allocate(count*sizeof(MessageUnit));
+	}
+
+	MPI_Recv(incoming,count,datatype,actualSource,actualTag,MPI_COMM_WORLD,&status);
+
+	Message aMessage(incoming,count,m_rank,actualTag,actualSource);
+	inbox->push_back(aMessage);
+
+	#ifdef ASSERT
+	assert(aMessage.getDestination() == m_rank);
+	#endif
+
+	m_receivedMessages++;
+
+}
+
+void MessagesHandler::initialiseMembers(){
+	#ifdef CONFIG_COMM_PERSISTENT
+	// the ring itself  contain requests ready to receive messages
+	m_ringSize=m_size;
+
+	m_ring=(MPI_Request*)__Malloc(sizeof(MPI_Request)*m_ringSize,"RAY_MALLOC_TYPE_PERSISTENT_MESSAGE_RING",false);
+	m_buffers=(uint8_t*)__Malloc(MAXIMUM_MESSAGE_SIZE_IN_BYTES*m_ringSize,"RAY_MALLOC_TYPE_PERSISTENT_MESSAGE_BUFFERS",false);
+	m_head=0;
+
+	// post a few receives.
+	for(int i=0;i<m_ringSize;i++){
+		uint8_t*buffer=m_buffers+i*MAXIMUM_MESSAGE_SIZE_IN_BYTES;
+		MPI_Recv_init(buffer,MAXIMUM_MESSAGE_SIZE_IN_BYTES/sizeof(MessageUnit),m_datatype,
+			MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,m_ring+i);
+		MPI_Start(m_ring+i);
+	}
+
+	#endif /* CONFIG_COMM_PERSISTENT */
+}
+
+void MessagesHandler::freeLeftovers(){
+
+	#ifdef CONFIG_COMM_IRECV_TESTANY
+	destroy_irecv_testany();
+	#endif /* CONFIG_COMM_IRECV_TESTANY */
+
+	#ifdef CONFIG_COMM_PERSISTENT
+
+	for(int i=0;i<m_ringSize;i++){
+		MPI_Cancel(m_ring+i);
+		MPI_Request_free(m_ring+i);
+	}
+
+	__Free(m_ring,"RAY_MALLOC_TYPE_PERSISTENT_MESSAGE_RING",false);
+	m_ring=NULL;
+	__Free(m_buffers,"RAY_MALLOC_TYPE_PERSISTENT_MESSAGE_BUFFERS",false);
+	m_buffers=NULL;
+
+	#endif /* CONFIG_COMM_PERSISTENT */
+
+	__Free(m_messageStatistics,"RAY_MALLOC_TYPE_MESSAGE_STATISTICS",false);
+	m_messageStatistics=NULL;
+}
+
+void MessagesHandler::constructor(int*argc,char***argv){
+
+	m_destroyed=false;
+
+	m_sentMessages=0;
+	m_receivedMessages=0;
+	m_datatype=MPI_UNSIGNED_LONG_LONG;
+
+	MPI_Init(argc,argv);
+
+	char serverName[1000];
+	int len;
+
+	/** initialize the message passing interface stack */
+	MPI_Get_processor_name(serverName,&len);
+	MPI_Comm_rank(MPI_COMM_WORLD,&m_rank);
+	MPI_Comm_size(MPI_COMM_WORLD,&m_size);
+	initialiseMembers();
+	m_processorName=serverName;
+
+	m_numberOfDirtyBuffers=0;
+
+	m_maximumDirtyBuffers=m_numberOfDirtyBuffers;
+
+	m_dirtyBuffers=NULL;
+
+	m_linearSweeps=0;
+
+/**
+ * internally, there are N buffers for MPI_Isend. However,
+ * these slots become dirty when they are used and become
+ * clean again when MPI_Test says so.
+ * But we don't want to do too much sweep operations. Instead,
+ * we want amortized operations.
+ */
+
+	m_minimumNumberOfDirtyBuffersForSweep=__NOT_SET;
+	m_minimumNumberOfDirtyBuffersForWarning=__NOT_SET;
+
+	#ifdef CONFIG_COMM_IRECV_TESTANY
+	m_requests=NULL;
+	#endif
+}
+
+void MessagesHandler::createBuffers(){
+
+	/** initialize message statistics to 0 */
+	m_messageStatistics=(uint64_t*)__Malloc(RAY_MPI_TAG_DUMMY*m_size*sizeof(uint64_t),"RAY_MALLOC_TYPE_MESSAGE_STATISTICS",false);
+	for(int rank=0;rank<m_size;rank++){
+		for(int tag=0;tag<RAY_MPI_TAG_DUMMY;tag++){
+			m_messageStatistics[rank*RAY_MPI_TAG_DUMMY+tag]=0;
+		}
+	}
+
+	#ifdef CONFIG_COMM_IPROBE_ROUND_ROBIN
+	// start with the first connection
+	m_currentRankIndexToTryToReceiveFrom=0;
+	#endif /* CONFIG_COMM_IPROBE_ROUND_ROBIN */
+
+	// initialize connections
+	for(int i=0;i<m_size;i++)
+		m_connections.push_back(i);
+
+	#ifdef CONFIG_COMM_IPROBE_ROUND_ROBIN
+	cout<<"[MessagesHandler] Will use "<<m_connections.size()<<" connections for round-robin reception."<<endl;
+	#endif
+
+	m_peers=m_connections.size();
+}
+
+
+void MessagesHandler::destructor(){
+	if(!m_destroyed){
+		MPI_Finalize();
+		m_destroyed=true;
+	}
+
+	freeLeftovers();
+
+}
+
+string*MessagesHandler::getName(){
+	return &m_processorName;
+}
+
+int MessagesHandler::getRank(){
+	return m_rank;
+}
+
+int MessagesHandler::getSize(){
+	return m_size;
+}
+
+void MessagesHandler::barrier(){
+	MPI_Barrier(MPI_COMM_WORLD);
+}
+
+void MessagesHandler::version(int*a,int*b){
+	MPI_Get_version(a,b);
+}
+
+void MessagesHandler::appendStatistics(const char*file){
+	/** add an entry for RAY_MPI_TAG_GOOD_JOB_SEE_YOU_SOON_REPLY
+ * 	because this message is sent after writting the current file
+ *
+ * 	actually, this RAY_MPI_TAG_GOOD_JOB_SEE_YOU_SOON_REPLY is not accounted for because
+ * 	it is sent after printing the statistics.
+ */
+
+	cout<<"MessagesHandler::appendStatistics file= "<<file<<endl;
+
+	ofstream fp;
+	fp.open(file,ios_base::out|ios_base::app);
+	vector<int> activePeers;
+	for(int destination=0;destination<m_size;destination++){
+		bool active=false;
+		for(int tag=0;tag<RAY_MPI_TAG_DUMMY;tag++){
+			uint64_t count=m_messageStatistics[destination*RAY_MPI_TAG_DUMMY+tag];
+
+			if(count==0)
+				continue;
+
+			active=true;
+
+			fp<<m_rank<<"\t"<<destination<<"\t"<<MESSAGE_TAGS[tag]<<"\t"<<count<<"\n";
+		}
+		if(active)
+			activePeers.push_back(destination);
+	}
+	fp.close();
+
+	cout<<"[MessagesHandler] Hello, this is the layered communication vessel, status follows."<<endl;
+	cout<<"Rank "<<m_rank<<": sent "<<m_sentMessages<<" messages, received "<<m_receivedMessages<<" messages."<<endl;
+	cout<<"Rank "<<m_rank<<": the maximum number of dirty buffers was "<<m_maximumDirtyBuffers<<endl;
+	cout<<"Rank "<<m_rank<<": "<<m_linearSweeps<<" linear sweep operations (threshold: ";
+	cout<<m_minimumNumberOfDirtyBuffersForSweep<<" dirty buffers)"<<endl;
+	cout<<"Rank "<<m_rank<<": Active peers (including self): "<<activePeers.size()<<" list:";
+
+	for(int i=0;i<(int)activePeers.size();i++){
+		cout<<" "<<activePeers[i];
+	}
+	cout<<endl;
+
+	cout<<"[MessagesHandler] Over and out."<<endl;
+}
+
+string MessagesHandler::getMessagePassingInterfaceImplementation(){
+	ostringstream implementation;
+
+	#ifdef MPICH2
+        implementation<<"MPICH2 (MPICH2) "<<MPICH2_VERSION;
+	#endif
+
+	#ifdef OMPI_MPI_H
+        implementation<<"Open-MPI (OMPI_MPI_H) "<<OMPI_MAJOR_VERSION<<"."<<OMPI_MINOR_VERSION<<"."<<OMPI_RELEASE_VERSION;
+	#endif
+
+	if(implementation.str().length()==0)
+		implementation<<"Unknown";
+	return implementation.str();
+}
+
+// set connections to probe from
+// we assume that connections are sorted.
+void MessagesHandler::setConnections(vector<int>*connections){
+
+	bool hasSelf=false;
+	for(int i=0;i<(int)connections->size();i++){
+		if(connections->at(i)==m_rank){
+			hasSelf=true;
+			break;
+		}
+	}
+
+	m_connections.clear();
+
+	// we have to make sure to insert the self link
+	// at the good place.
+
+	for(int i=0;i<(int)connections->size();i++){
+
+		Rank otherRank=connections->at(i);
+
+		// add the self rank
+		if(!hasSelf){
+			if(m_rank < otherRank){
+				m_connections.push_back(m_rank);
+				hasSelf=true;
+			}
+		}
+
+		m_connections.push_back(otherRank);
+	}
+
+	// if we have not added the self link yet,
+	// it is because it is greater.
+	if(!hasSelf){
+		m_connections.push_back(m_rank);
+		hasSelf=true;
+	}
+
+	cout<<"[MessagesHandler] after runtime re-configuration, will use "<<m_connections.size()<<" connections for round-robin reception."<<endl;
+
+	m_peers=m_connections.size();
+}
+
+void MessagesHandler::registerPlugin(ComputeCore*core){
+	m_plugin=core->allocatePluginHandle();
+
+	core->setPluginName(m_plugin,"MessagesHandler");
+	core->setPluginDescription(m_plugin,"MPI wrapper with round-robin policy (bundled with RayPlatform)");
+	core->setPluginAuthors(m_plugin,"Sébastien Boisvert");
+	core->setPluginLicense(m_plugin,"GNU Lesser General License version 3");
+
+	RAY_MPI_TAG_DUMMY=core->allocateMessageTagHandle(m_plugin);
+	core->setMessageTagSymbol(m_plugin,RAY_MPI_TAG_DUMMY,"RAY_MPI_TAG_DUMMY");
+
+	createBuffers();
+}
+
+void MessagesHandler::resolveSymbols(ComputeCore*core){
+	RAY_MPI_TAG_DUMMY=core->getMessageTagFromSymbol(m_plugin,"RAY_MPI_TAG_DUMMY");
+}
+
diff --git a/RayPlatform/communication/MessagesHandler.h b/RayPlatform/communication/MessagesHandler.h
new file mode 100644
index 0000000..68ecb98
--- /dev/null
+++ b/RayPlatform/communication/MessagesHandler.h
@@ -0,0 +1,287 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _MessagesHandler
+#define _MessagesHandler
+
+/* Many communication models are implemented:
+ * latencies are for a system with 36 cores (or 120 cores), QLogic interconnect, 
+ *  and Performance scaled messaging
+ * - CONFIG_COMM_IPROBE_ANY_SOURCE  
+     	latency(36): 16 micro seconds
+	latency(120): 19 microseconds
+	no fairness, possible starvation
+ * - CONFIG_COMM_IPROBE_ROUND_ROBIN 
+     	latency(36):, 18 microseconds
+     	latency(120): 23 microseconds
+     	latency with 1008 cores: 78 (84*12): microseconds (without -route-messages.)
+     	with fairness, no starvation
+ * - CONFIG_COMM_PERSISTENT (latency(36): , no fairness)
+     	latency(36): 28 micro seconds
+	latency(120): 75 microseconds
+	no fairness, possible starvation
+ * - CONFIG_COMM_IRECV_TESTANY (no data)
+ */
+
+/*
+ * only one must be set
+ */
+
+/*
+ * Persistent communication pumps the message more rapidly
+ * on some systems
+ */
+//#define CONFIG_COMM_PERSISTENT
+
+/**
+ *  Use round-robin reception.
+ */
+//#define CONFIG_COMM_IPROBE_ROUND_ROBIN
+
+/* this configuration may be important for low latency */
+/* uncomment if you want to try it */
+/* this is only useful with CONFIG_COMM_IPROBE_ROUND_ROBIN */
+//#define CONFIG_ONE_IPROBE_PER_TICK
+
+/*
+ * Probing any message, then receive it.
+ * This model is used by Converse/CHARM++/NAMD.
+ */
+#define CONFIG_COMM_IPROBE_ANY_SOURCE
+
+/*
+ * Non-blocking reception. This was suggested by Pavan Balaji
+ * and Jeff Squyres.
+ * It does not work that well on the IBM Blue Gene /Q.
+ */
+//#define CONFIG_COMM_IRECV_TESTANY
+
+#include <mpi.h> // this is the only reference to MPI
+
+#include <memory/MyAllocator.h>
+#include <communication/Message.h>
+//#include <core/common_functions.h>
+#include <memory/RingAllocator.h>
+#include <structures/StaticVector.h>
+#include <plugins/CorePlugin.h>
+
+class ComputeCore;
+
+#include <string>
+#include <vector>
+using namespace std;
+
+/**
+ * A data model for storing dirty buffers
+ */
+class DirtyBuffer{
+public:
+	void*m_buffer;
+	MPI_Request m_messageRequest;
+	Rank m_destination;
+	MessageTag m_messageTag;
+};
+
+/**
+ * Software layer to handle messages.
+ * MessagesHandler is the only part of Ray that is aware of the 
+ * message-passing interface.
+ * All the other parts rely only on a simple inbox and a simple outbox.
+ * These boxes of messages could be implemented with something else 
+ * than message-passing interface.
+ *
+ * Messages are sent with MPI_Isend and buffers are managed by a dirty buffer
+ * laundry list.
+ *
+ * 4 communication models are implemented:
+ *
+ * CONFIG_COMM_IPROBE_ANY_SOURCE -> MPI_Iprobe with any source + MPI_Recv
+ * CONFIG_COMM_IRECV_TESTANY -> MPI_Irecv + MPI_Testany
+ * CONFIG_COMM_IPROBE_ROUND_ROBIN -> MPI_Iprobe with round-robin source + MPI_Recv
+ * CONFIG_COMM_PERSISTENT -> MPI_Recv_init + MPI_Test 
+ *
+ * \author Sébastien Boisvert
+ */
+class MessagesHandler: public CorePlugin{
+
+	int m_minimumNumberOfDirtyBuffersForSweep;
+
+	int m_minimumNumberOfDirtyBuffersForWarning;
+
+/** prints dirty buffers **/
+	void printDirtyBuffers();
+
+	// the number of peers for communication
+	int m_peers;
+
+	DirtyBuffer*m_dirtyBuffers;
+
+	int m_numberOfDirtyBuffers;
+	int m_maximumDirtyBuffers;
+	int m_dirtyBufferSlots;
+
+	MessageTag RAY_MPI_TAG_DUMMY;
+
+	bool m_destroyed;
+
+	vector<int> m_connections;
+
+	Rank m_rank;
+	int m_size;
+	/** this variable stores counts for sent messages */
+	uint64_t*m_messageStatistics;
+
+	/** messages sent */
+	uint64_t m_sentMessages;
+	/** messages received */
+	uint64_t m_receivedMessages;
+
+/**
+ * 	In Ray, all messages have buffer of the same type
+ */
+	MPI_Datatype m_datatype;
+
+	string m_processorName;
+
+#ifdef CONFIG_COMM_IPROBE_ROUND_ROBIN
+	/** round-robin head */
+	int m_currentRankIndexToTryToReceiveFrom;
+#endif /* CONFIG_COMM_IPROBE_ROUND_ROBIN */
+
+#ifdef CONFIG_COMM_PERSISTENT
+
+	/** the number of buffered messages in the persistent layer */
+	int m_bufferedMessages;
+
+	/** linked lists */
+	MessageNode**m_heads;
+
+	/** linked lists */
+	MessageNode**m_tails;
+
+	/** the number of persistent requests in the ring */
+	int m_ringSize;
+
+	/** the current persistent request in the ring */
+	int m_head;
+
+	/** the ring of persistent requests */
+	MPI_Request*m_ring;
+
+	/** the ring of buffers for persistent requests */
+	uint8_t*m_buffers;
+
+#endif /* CONFIG_COMM_PERSISTENT */
+
+
+#ifdef CONFIG_COMM_IRECV_TESTANY
+
+	int m_numberOfNonBlockingReceives;
+	MPI_Request*m_requests;
+	uint8_t*m_receptionBuffers;
+	int m_bufferSize;
+
+#endif /* CONFIG_COMM_IRECV_TESTANY */
+
+	/** initialize persistent communication parameters */
+	void initialiseMembers();
+
+	/** probe and read a message -- this method is not utilised */
+	void probeAndRead(int source,int tag,StaticVector*inbox,RingAllocator*inboxAllocator);
+
+#ifdef CONFIG_COMM_PERSISTENT
+	/** pump a message from the persistent ring */
+	void pumpMessageFromPersistentRing(StaticVector*inbox,RingAllocator*inboxAllocator);
+#endif /* CONFIG_COMM_PERSISTENT */
+
+#ifdef CONFIG_COMM_IPROBE_ROUND_ROBIN
+	/** select and fetch a message from the internal messages using a round-robin policy */
+	void roundRobinReception(StaticVector*inbox,RingAllocator*inboxAllocator);
+#endif /* CONFIG_COMM_IPROBE_ROUND_ROBIN */
+
+#ifdef CONFIG_COMM_IRECV_TESTANY
+
+	void receiveMessages_irecv_testany(StaticVector*inbox,RingAllocator*inboxAllocator);
+	void init_irecv_testany(RingAllocator*inboxAllocator);
+	void destroy_irecv_testany();
+	void startNonBlockingReception(int handle);
+
+#endif /* CONFIG_COMM_IRECV_TESTANY */
+
+	void createBuffers();
+
+	void checkDirtyBuffer(RingAllocator*outboxBufferAllocator,int i);
+	void cleanDirtyBuffers(RingAllocator*outboxBufferAllocator);
+	uint64_t m_linearSweeps;
+	void initializeDirtyBuffers(RingAllocator*outboxBufferAllocator);
+
+public:
+	/** initialize the message handler
+ * 	*/
+	void constructor(int*argc,char***argv);
+
+	/**
+ *  send a message or more
+ */
+	void sendMessages(StaticVector*outbox,RingAllocator*outboxBufferAllocator);
+
+
+
+	/**
+ * receive one or zero message.
+ * the others, if any, will be picked up in the next iteration
+ */
+	void receiveMessages(StaticVector*inbox,RingAllocator*inboxAllocator);
+
+	/** free the ring elements */
+	void freeLeftovers();
+
+	/** get the processor name, usually set to the server name */
+	string*getName();
+
+	/** get the identifier of the current message passing interface rank */
+	int getRank();
+
+	/** get the number of ranks */
+	int getSize();
+
+	/** makes a barrier */
+	void barrier();
+
+	/** returns the version of the message passing interface standard that is available */
+	void version(int*a,int*b);
+
+	void destructor();
+
+	/** write sent message counts to a file */
+	void appendStatistics(const char*file);
+
+	string getMessagePassingInterfaceImplementation();
+
+	void setConnections(vector<int>*connections);
+
+	void registerPlugin(ComputeCore*core);
+	void resolveSymbols(ComputeCore*core);
+};
+
+#endif /* _MessagesHandler */
+
+
diff --git a/RayPlatform/communication/VirtualCommunicator.cpp b/RayPlatform/communication/VirtualCommunicator.cpp
new file mode 100644
index 0000000..2aa2296
--- /dev/null
+++ b/RayPlatform/communication/VirtualCommunicator.cpp
@@ -0,0 +1,472 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+/* #define DEBUG_VIRTUAL_COMMUNICATOR */
+
+#include <communication/VirtualCommunicator.h>
+#include <core/OperatingSystem.h>
+#include <core/types.h>
+#include <core/ComputeCore.h>
+
+#include <assert.h>
+#include <iostream>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+using namespace std;
+
+/** set the number of elements per message for a given tag */
+void VirtualCommunicator::setElementsPerQuery(int tag,int size){
+	#ifdef ASSERT
+	assert(m_elementSizes.count(tag)==0);
+	assert(tag!=INVALID_HANDLE);
+	#endif
+
+	m_elementSizes[tag]=size;
+}
+
+/** get the number of elements per message for a given tag */
+int VirtualCommunicator::getElementsPerQuery(int tag){
+	#ifdef ASSERT
+	assert(m_elementSizes.count(tag)!=0);
+	#endif
+
+	return m_elementSizes[tag];
+}
+
+/**  associate the reply message tag to a message tag */
+void VirtualCommunicator::setReplyType(int query,int reply){
+	#ifdef ASSERT
+	assert(m_replyTagToQueryTag.count(reply)==0);
+	#endif
+
+	m_replyTagToQueryTag[reply]=query;
+
+	#ifdef ASSERT
+	assert(m_reverseReplyMap.count(query) == 0);
+	#endif
+
+	m_reverseReplyMap[query]=reply;
+}
+
+int VirtualCommunicator::getReplyType(int tag){
+	#ifdef ASSERT
+	if(m_reverseReplyMap.count(tag) == 0){
+		cout<<"Error: "<<MESSAGE_TAGS[tag]<<" is not in the reverse-map"<<endl;
+	}
+	assert(m_reverseReplyMap.count(tag) > 0);
+	#endif
+	
+	return m_reverseReplyMap[tag];
+}
+
+/** push a message
+ * this may trigger an actual message being flushed in the
+ * message-passing interface stack 
+ */
+void VirtualCommunicator::pushMessage(WorkerHandle workerId,Message*message){
+	int tag=message->getTag();
+
+	#ifdef ASSERT
+	assert(m_elementSizes.count(tag)>0);
+	#endif
+
+	int period=m_elementSizes[tag];
+	int count=message->getCount();
+
+	#ifdef ASSERT
+	if(count > period){
+		cout<<"Error, count= "<<count<<" but period is "<<period<<endl;
+		cout<<"Tag= "<<MESSAGE_TAGS[tag]<<endl;
+	}
+	assert(count<=period);
+	#endif
+
+	m_pushedMessages++;
+	#ifdef ASSERT
+	if(m_elementsForWorkers.count(workerId)>0){
+		cout<<"Error: there is already a pending message for worker "<<workerId<<", will not add message with tag="<<MESSAGE_TAGS[message->getTag()]<<endl;
+		cout<<"Did you forget to pull a reply with isMessageProcessed and getMessageResponseElements ?"<<endl;
+		cout<<"It is likely if you mix virtual messages with bare messages !"<<endl;
+	}
+	assert(m_elementsForWorkers.count(workerId)==0);
+	#endif
+	m_globalPushedMessageStatus=true;
+	m_localPushedMessageStatus=true;
+
+	int destination=message->getDestination();
+
+	#ifdef ASSERT
+	if(!(destination>=0&&destination<m_size)){
+		cout<<"Error: tag="<<message->getTag()<<" destination="<<destination<<" (INVALID)"<<endl;
+	}
+	assert(destination>=0&&destination<m_size);
+	#endif
+
+	#ifdef ASSERT
+	assert(m_elementSizes.count(tag)>0);
+	#endif
+
+	/**  generate   a group key for the message 
+ * 	this is used for priority calculation
+ * 	*/
+	uint64_t elementId=getMessageUniqueId(destination,tag);
+	int oldPriority=0;
+	/* delete old priority */
+	if(m_messageContent.count(tag)>0&&m_messageContent[tag].count(destination)>0){
+		oldPriority=m_messageContent[tag][destination].size();
+		m_priorityQueue[oldPriority].erase(elementId);
+		if(m_priorityQueue[oldPriority].size()==0){
+			m_priorityQueue.erase(oldPriority);
+		}
+	}
+	int newPriority=oldPriority+count;
+	m_priorityQueue[newPriority].insert(elementId);
+
+	#ifdef ASSERT
+	assert(count>0);
+	#endif
+
+	MessageUnit*buffer=(MessageUnit*)message->getBuffer();
+	for(int i=0;i<count;i++){// count is probably 1...
+		MessageUnit element=buffer[i];
+		m_messageContent[tag][destination].push_back(element);
+	}
+
+	/** add the worker workerId  to the list of workers that pushed a message of type
+ * 	tag to message-passing interface  rank destination
+ */
+	m_workerCurrentIdentifiers[tag][destination].push_back(workerId);
+
+	#ifdef ASSERT
+	assert(m_elementSizes.count(tag)>0);
+	#endif
+
+	/** check if the current size is good enough to flush the whole thing */
+	int currentSize=m_workerCurrentIdentifiers[tag][destination].size();
+
+	/*
+ *	maximum number of pushed messages
+ */
+	int threshold=MAXIMUM_MESSAGE_SIZE_IN_BYTES/sizeof(MessageUnit)/period;
+
+	/** this whole block makes sure that the communicator is not overloaded */
+	#ifdef ASSERT
+	assert(m_elementSizes.count(tag)>0);
+	assert(period>=1);
+	assert(threshold<=(int)(MAXIMUM_MESSAGE_SIZE_IN_BYTES/sizeof(MessageUnit)));
+	if(currentSize>threshold){
+		cout<<"Fatal: too much bits, tag= "<<MESSAGE_TAGS[tag]<<" Threshold= "<<threshold<<" pushed messages; Actual= "<<currentSize<<" pushed messages; Period= "<<period<<" MessageUnit/message; Count= "<<count<<" Priority= "<<newPriority<<" Destination: "<<destination<<endl;
+		cout<<"This usually means that you did not use the VirtualCommunicator API correctly."<<endl;
+		cout<<"Be careful not to push too many messages if the VirtualCommunicator is not ready."<<endl;
+		cout<<"IMPORTANT: did you add entries for reply tags.txt and tag sizes ?"<<endl;
+	}
+	assert(currentSize<=threshold);
+	#endif
+
+	if(currentSize>=threshold){
+		// must flush the message
+		flushMessage(tag,destination);
+	}
+}
+
+void VirtualCommunicator::flushMessage(int tag,int destination){
+	#ifdef DEBUG_VIRTUAL_COMMUNICATOR
+	cout<<"VirtualCommunicator:: sending multiplexed message to "<<destination<<endl;
+	#endif
+
+	m_flushedMessages++;
+
+	#ifdef ASSERT
+	assert(m_messageContent.count(tag)>0&&m_messageContent[tag].count(destination)>0);
+	#endif
+
+	// find the priority and erase it
+	int priority=m_messageContent[tag][destination].size();
+	uint64_t elementId=getMessageUniqueId(destination,tag);
+	m_priorityQueue[priority].erase(elementId);
+	if(m_priorityQueue[priority].size()==0){
+		m_priorityQueue.erase(priority);
+	}
+
+	m_activeDestination=destination;
+	m_activeTag=tag;
+	int currentSize=priority;
+
+	#ifdef ASSERT
+	if(currentSize==0){
+		cout<<"Cannot flush empty buffer!"<<endl;
+	}
+	assert(currentSize>0);
+	int requiredResponseLength=m_workerCurrentIdentifiers[tag][destination].size()*m_elementSizes[tag]*sizeof(MessageUnit);
+	assert(requiredResponseLength<=MAXIMUM_MESSAGE_SIZE_IN_BYTES);
+	#endif
+
+	MessageUnit*messageContent=(MessageUnit*)m_outboxAllocator->allocate(currentSize*sizeof(MessageUnit));
+
+	for(int j=0;j<currentSize;j++){
+		messageContent[j]=m_messageContent[tag][destination][j];
+	}
+
+	m_messageContent[tag].erase(destination);
+	if(m_messageContent[tag].size()==0){
+		m_messageContent.erase(tag);
+	}
+
+	Message aMessage(messageContent,currentSize,destination,tag,m_rank);
+	m_outbox->push_back(aMessage);
+
+	m_pendingMessages++;
+}
+
+bool VirtualCommunicator::isMessageProcessed(WorkerHandle workerId){
+	return m_elementsForWorkers.count(workerId)>0;
+}
+
+void VirtualCommunicator::getMessageResponseElements(WorkerHandle workerId,vector<MessageUnit>*out){
+	#ifdef ASSERT
+	assert(isMessageProcessed(workerId));
+	#endif
+
+	for(int i=0;i<(int)(m_elementsForWorkers[workerId].size());i++)
+		out->push_back(m_elementsForWorkers[workerId][i]);
+
+	m_elementsForWorkers.erase(workerId);
+
+	#ifdef ASSERT
+	assert(!isMessageProcessed(workerId));
+	#endif
+}
+
+void VirtualCommunicator::constructor(int rank,int size,RingAllocator*outboxAllocator,StaticVector*inbox,StaticVector*outbox){
+	m_debug=false;
+
+	if(m_debug)
+		cout<<"Rank "<<rank<<" Initializing VirtualCommunicator"<<endl;
+
+	resetCounters();
+
+	m_rank=rank;
+	m_size=size;
+	m_outboxAllocator=outboxAllocator;
+	m_inbox=inbox;
+	m_outbox=outbox;
+	m_pendingMessages=0;
+
+	resetLocalPushedMessageStatus();
+	resetGlobalPushedMessageStatus();
+}
+
+void VirtualCommunicator::resetCounters(){
+	m_pushedMessages=0;
+	m_flushedMessages=0;
+
+
+}
+
+void VirtualCommunicator::processInbox(vector<WorkerHandle>*activeWorkers){
+	if(m_pendingMessages>0&&m_inbox->size()>0){// we have mail
+		Message*message=m_inbox->at(0);// there is 0 or 1 message in the inbox
+		int incomingTag=message->getTag();
+		int source=message->getSource();
+		if(m_replyTagToQueryTag.count(incomingTag)==0){
+			return;
+		}
+
+		#ifdef ASSERT
+		assert(m_replyTagToQueryTag.count(incomingTag)>0);
+		#endif
+
+		int queryTag=m_replyTagToQueryTag[incomingTag];
+		if(m_activeTag==queryTag&&m_activeDestination==source){
+			#ifdef DEBUG_VIRTUAL_COMMUNICATOR
+			cout<<"VirtualCommunicator: receiving multiplexed message, de-multiplexing data..."<<endl;
+			#endif
+
+			m_pendingMessages--;
+			cout.flush();
+			MessageUnit*buffer=(MessageUnit*)message->getBuffer();
+
+			#ifdef ASSERT
+			assert(m_elementSizes.count(queryTag)>0);
+			#endif
+
+			int elementsPerWorker=m_elementSizes[queryTag];
+			vector<WorkerHandle> workers=m_workerCurrentIdentifiers[m_activeTag][m_activeDestination];
+			m_workerCurrentIdentifiers[m_activeTag][m_activeDestination].clear();
+			
+			#ifdef ASSERT
+			assert(workers.size()>0);
+			assert(elementsPerWorker>0);
+			int count=message->getCount();
+			if(count==0){
+				cout<<"QueryTag = "<<queryTag<<endl;
+			}
+			assert(count>0);
+			if(count!=(int)workers.size()*elementsPerWorker){
+				cout<<"Rank="<<m_rank<<" Count="<<count<<" Workers="<<workers.size()<<" ElementsPerWorker="<<elementsPerWorker<<" QueryTag="<<MESSAGE_TAGS[queryTag]<<endl;
+			}
+			assert(count==(int)workers.size()*elementsPerWorker);
+			#endif
+
+			// add the workers to a list
+			// so they can be activated again
+			for(int i=0;i<(int)workers.size();i++){
+				WorkerHandle workerId=workers[i];
+				activeWorkers->push_back(workerId);
+				if(m_debug){
+					cout<<"Reactivating "<<workerId<<" tag="<<queryTag<<endl;
+				}
+				int basePosition=i*elementsPerWorker;
+
+				#ifdef ASSERT
+				if(m_elementsForWorkers.count(workerId)>0){
+					cout<<"there already are elements for "<<workerId<<endl;
+				}
+				assert(m_elementsForWorkers.count(workerId)==0);
+				#endif
+
+				// classify the data and bins
+				for(int j=0;j<elementsPerWorker;j++){
+					uint64_t element=buffer[basePosition+j];
+					m_elementsForWorkers[workerId].push_back(element);
+				}
+
+				// make sure that is someone 
+				// asks if workerId can fetch its thing,
+				// it will return true.
+				#ifdef ASSERT
+				assert(isMessageProcessed(workerId));
+				#endif
+			}
+		}
+	}
+
+	#ifdef ASSERT
+	assert(m_pendingMessages>=0);
+	#endif
+}
+
+bool VirtualCommunicator::getLocalPushedMessageStatus(){
+	return m_localPushedMessageStatus;
+}
+
+void VirtualCommunicator::resetLocalPushedMessageStatus(){
+	m_localPushedMessageStatus=false;
+}
+
+void VirtualCommunicator::resetGlobalPushedMessageStatus(){
+	m_globalPushedMessageStatus=false;
+}
+
+bool VirtualCommunicator::getGlobalPushedMessageStatus(){
+	return m_globalPushedMessageStatus;
+}
+
+bool VirtualCommunicator::isReady(){
+	return m_pendingMessages==0;
+}
+
+// force the first encountered thing
+void VirtualCommunicator::forceFlush(){
+	if(m_debug){
+		cout<<__func__<<endl;
+	}
+
+	if(m_priorityQueue.size()==0){
+		if(m_debug){
+			cout<<"queue is empty"<<endl;
+		}
+		return;
+	}
+
+	// if forceFlush is called
+	// and there are no message
+	// the thing will crash 
+	// it is designed like that
+	#ifdef ASSERT
+	assert(!m_priorityQueue.rbegin()->second.empty());
+	#endif
+
+	uint64_t elementId=*(m_priorityQueue.rbegin()->second.begin());
+	int selectedDestination=getDestinationFromMessageUniqueId(elementId);
+	int selectedTag=getTagFromMessageUniqueId(elementId);
+
+	#ifdef ASSERT
+	assert(m_messageContent.count(selectedTag)>0&&m_messageContent[selectedTag].count(selectedDestination)>0);
+	assert(!m_messageContent[selectedTag][selectedDestination].empty());
+	#endif
+
+	flushMessage(selectedTag,selectedDestination);
+}
+
+bool VirtualCommunicator::hasMessagesToFlush(){
+	return !m_messageContent.empty();
+}
+
+bool VirtualCommunicator::nextIsAlmostFull(){
+	if(m_priorityQueue.empty()){
+		return false;
+	}
+	
+	uint64_t elementId=*(m_priorityQueue.rbegin()->second.begin());
+	int selectedDestination=getDestinationFromMessageUniqueId(elementId);
+	int selectedTag=getTagFromMessageUniqueId(elementId);
+	
+	int period=m_elementSizes[selectedTag];
+	int currentSize=m_messageContent[selectedTag][selectedDestination].size();
+	int threshold=MAXIMUM_MESSAGE_SIZE_IN_BYTES/8;
+	int value=currentSize*period;
+
+	return value>=threshold;
+}
+
+void VirtualCommunicator::printStatistics(){
+	double ratio=100.0*m_flushedMessages;
+
+	if(m_pushedMessages!=0){
+		ratio/=m_pushedMessages;
+	}
+
+	cout<<"Rank "<<m_rank<<" : VirtualCommunicator (service provided by VirtualCommunicator): "<<m_pushedMessages;
+	cout<<" virtual messages generated "<<m_flushedMessages;
+	cout<<" real messages ("<<ratio<<"%)"<<endl;
+}
+
+/** debugging will display a lot of messages */
+void VirtualCommunicator::setDebug(){
+	m_debug=true;
+}
+
+uint64_t VirtualCommunicator::getMessageUniqueId(Rank destination ,int tag){
+	uint64_t a=tag;
+	a=a*MAX_NUMBER_OF_MPI_PROCESSES+destination;
+	return a;
+}
+
+int VirtualCommunicator::getTagFromMessageUniqueId(uint64_t a){
+	return a/MAX_NUMBER_OF_MPI_PROCESSES;
+}
+
+Rank VirtualCommunicator::getDestinationFromMessageUniqueId(uint64_t a){
+	int rank=a%MAX_NUMBER_OF_MPI_PROCESSES;
+	return rank;
+}
+
diff --git a/RayPlatform/communication/VirtualCommunicator.h b/RayPlatform/communication/VirtualCommunicator.h
new file mode 100644
index 0000000..811959e
--- /dev/null
+++ b/RayPlatform/communication/VirtualCommunicator.h
@@ -0,0 +1,219 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+// TYPE: COMMUNICATION
+
+#ifndef _VirtualCommunicator
+#define _VirtualCommunicator
+
+#include <memory/RingAllocator.h>
+#include <structures/StaticVector.h>
+#include <communication/Message.h>
+#include <memory/MyAllocator.h>
+
+#include <map>
+#include <vector>
+#include <stdint.h>
+#include <queue>
+using namespace std;
+
+/**
+ * this class provides an architecture for virtualization of message communication.
+ *
+ * This means that messages are grouped, but the programmer don't have to group them himself...
+ *
+ * Instead of using the standard m_inbox and m_outbox in Ray, the user uses
+ * the methods below.
+ *
+ * The object is specific to a step of the algorithm because worker Identifiers are attributed.
+ *
+* this class is event-driven and tag-specific and destination-specific
+ * \author Sébastien Boisvert
+*/
+class VirtualCommunicator{
+	bool m_debug;
+	uint64_t m_pushedMessages;
+	uint64_t m_flushedMessages;
+
+	// priority, elementId, QueueElement
+	map<int,set<uint64_t> > m_priorityQueue;
+
+	// associates an MPI tag with a length reservation.
+	// for instance, asking the coverage is 1 but asking ingoing edges is 5
+	// key: MPI tag
+	// number of elements per query
+	// getting ingoing edges for a vertex requires 5 because at most there will be 4 and the size is a requirement
+	map<int,int> m_elementSizes;
+
+	// indicates to who belongs each elements to communicate, grouped according to m_elementSizes
+	map<int,map<int,vector<WorkerHandle> > > m_workerCurrentIdentifiers;
+
+	// the message contents
+	// first key: MPI tag
+	// second key: MPI destination
+	// vector: contains elements to communicate
+	map<int,map<int,vector<MessageUnit> > > m_messageContent;
+
+	// response to give to workers
+	map<WorkerHandle,vector<MessageUnit> > m_elementsForWorkers;
+
+	// reply types.
+	map<int,int> m_replyTagToQueryTag;
+
+	map<int,int> m_reverseReplyMap;
+
+	int m_rank;
+	int m_size;
+	RingAllocator*m_outboxAllocator;
+	StaticVector*m_inbox;
+	StaticVector*m_outbox;
+	int m_activeDestination;
+	int m_activeTag;
+	int m_pendingMessages;
+
+	bool m_localPushedMessageStatus;
+	bool m_globalPushedMessageStatus;
+	// flush a message associated to a tag and a destination
+	void flushMessage(int tag,int destination);
+
+
+	Rank getDestinationFromMessageUniqueId(uint64_t a);
+	int getTagFromMessageUniqueId(uint64_t a);
+	uint64_t getMessageUniqueId(Rank destination,int tag);
+
+public:
+	/**
+ * initiate the object
+ * called once
+ * time complexity: constant
+ */ 
+	void constructor(int rank,int size,RingAllocator*outboxAllocator,StaticVector*inbox,StaticVector*outbox);
+	
+	/**
+ * associate a resonse tag to a query tag
+ * called once
+ * time complexity: constant
+ */
+	void setReplyType(int tag,int reply);
+
+	/**
+ * associate a period size to a tag type
+ * this is bounded by the maximum between the query size and the reply size for
+ * a single message
+ * called once
+ * time complexity: constant
+ */
+	void setElementsPerQuery(int tag,int size);
+	
+/**
+ * get the number of elements per query
+ */
+	int getElementsPerQuery(int tag);
+
+	/**
+ * this method must be called before calling workers.
+ * it will fetch messages from inbox according to ongoing queries.
+ * time complexity: linear in the number of workers to set active (in general about one hundred
+ */
+	void processInbox(vector<WorkerHandle>*activeWorkers);
+
+	/**
+ * push a worker message
+ * may not be sent instantaneously
+ * called once per iteration on workers
+ * if a worker calls it, then the iteration is stopped and won't be resumed until
+ * the VirtualCommunicator is ready.
+ * to do so, isReady is called before calling each worker.
+ * if a called calls pushMessage and because of that a buffer becomes full, then isReady will return false 
+ * for the next call
+ * time complexity: log (number of tags) + log(number of MPI ranks)
+ */
+	
+	void pushMessage(WorkerHandle workerId,Message*message);
+
+	/**
+ * return true if the response is ready to be read
+ * time complexity: log(number of workers)
+ */
+	bool isMessageProcessed(WorkerHandle workerId);
+	
+	/**
+ *
+ * after calling isMessageProcessed, the worker must retrieve its data with 
+ * getMessageResponseElements, else the whole thing will fail
+ *
+ * after reading the response, it is erased from
+ * the current object
+ * time complexity: log(number of workers)
+ */
+	void getMessageResponseElements(WorkerHandle workerId,vector<MessageUnit>*out);
+	
+/**
+ * if all workers are awaiting responses and 
+ * none of the buffer is full, then this forces the flushing of a buffer
+ * non-empty buffer.
+ * time complexity: log(number of priority values)
+ */
+	void forceFlush();
+
+	/**
+ * set the slot to false. The slot says yes if a message was pushed
+ * time complexity: constant
+ */
+	void resetLocalPushedMessageStatus();
+
+	/** get the slot.
+ * time complexity: constant
+ */
+	bool getLocalPushedMessageStatus();
+
+	/**
+ * reset the global slot
+ * time complexity: constant
+ */
+	void resetGlobalPushedMessageStatus();
+
+	/** get the slot.
+ * time complexity: constant
+ */
+	bool getGlobalPushedMessageStatus();
+
+	/** check if the communicator is ready
+ * time complexity: constant
+ */
+	bool isReady();
+
+/** check if the communicator has messages to flush
+ * time complexity: constant
+ */
+	bool hasMessagesToFlush();
+
+	bool nextIsAlmostFull();
+
+	void printStatistics();
+	void resetCounters();
+
+	void setDebug();
+
+	int getReplyType(int tag);
+
+};
+
+#endif
diff --git a/RayPlatform/communication/mpi_tags.cpp b/RayPlatform/communication/mpi_tags.cpp
new file mode 100644
index 0000000..07f35b4
--- /dev/null
+++ b/RayPlatform/communication/mpi_tags.cpp
@@ -0,0 +1,28 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+ 	Funding:
+Sébastien Boisvert has a scholarship from the Canadian Institutes of Health Research (Master's award: 200910MDR-215249-172830 and Doctoral award: 200902CGM-204212-172830).
+
+*/
+
+#include <communication/mpi_tags.h>
+
+char MESSAGE_TAGS[MAXIMUM_NUMBER_OF_TAG_HANDLERS][128];
+
diff --git a/RayPlatform/communication/mpi_tags.h b/RayPlatform/communication/mpi_tags.h
new file mode 100644
index 0000000..6d6df54
--- /dev/null
+++ b/RayPlatform/communication/mpi_tags.h
@@ -0,0 +1,33 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _mpi_tags
+#define _mpi_tags
+
+// tags for MPI
+// these are the message types used by Ray
+// Ray instances like to communicate a lots!
+
+#include <core/types.h>
+
+extern char MESSAGE_TAGS[MAXIMUM_NUMBER_OF_TAG_HANDLERS][128];
+
+#endif
diff --git a/RayPlatform/core/ComputeCore.cpp b/RayPlatform/core/ComputeCore.cpp
new file mode 100644
index 0000000..9fdb7ff
--- /dev/null
+++ b/RayPlatform/core/ComputeCore.cpp
@@ -0,0 +1,1681 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <core/ComputeCore.h>
+#include <core/OperatingSystem.h>
+#include <cryptography/crypto.h>
+#include <stdlib.h>
+#include <string.h> /* for strcpy */
+
+#ifdef ASSERT
+#include <assert.h>
+#endif
+
+#include <iostream>
+using namespace std;
+
+//#define CONFIG_DEBUG_SLAVE_SYMBOLS
+//#define CONFIG_DEBUG_MASTER_SYMBOLS
+//#define CONFIG_DEBUG_TAG_SYMBOLS
+//#define CONFIG_DEBUG_processData
+//#define CONFIG_DEBUG_CORE
+
+ComputeCore::ComputeCore(){
+}
+
+void ComputeCore::setSlaveModeObjectHandler(PluginHandle plugin,SlaveMode mode,SlaveModeHandler object){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationSlaveModeRange(plugin,mode))
+		return;
+
+	if(!validationSlaveModeOwnership(plugin,mode)){
+		cout<<"was trying to set object handler for mode "<<mode<<endl;
+		return;
+	}
+
+	#ifdef CONFIG_DEBUG_CORE
+	cout<<"setSlaveModeObjectHandler "<<SLAVE_MODES[mode]<<" to "<<object<<endl;
+	#endif
+
+	#ifdef ASSERT
+	assert(m_plugins.count(plugin)>0);
+	assert(m_plugins[plugin].hasSlaveMode(mode));
+	#endif
+
+	m_slaveModeExecutor.setObjectHandler(mode,object);
+
+	m_plugins[plugin].addRegisteredSlaveModeHandler(mode);
+}
+
+void ComputeCore::setMasterModeObjectHandler(PluginHandle plugin,MasterMode mode,MasterModeHandler object){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMasterModeRange(plugin,mode))
+		return;
+
+	if(!validationMasterModeOwnership(plugin,mode))
+		return;
+
+	#ifdef CONFIG_DEBUG_CORE
+	cout<<"setMasterModeObjectHandler "<<MASTER_MODES[mode]<<" to "<<object<<endl;
+	#endif
+
+	#ifdef ASSERT
+	assert(m_plugins.count(plugin)>0);
+	assert(m_plugins[plugin].hasMasterMode(mode));
+	#endif
+
+	m_masterModeExecutor.setObjectHandler(mode,object);
+
+	m_plugins[plugin].addRegisteredMasterModeHandler(mode);
+}
+
+void ComputeCore::setMessageTagObjectHandler(PluginHandle plugin,MessageTag tag,MessageTagHandler object){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMessageTagRange(plugin,tag))
+		return;
+
+	if(!validationMessageTagOwnership(plugin,tag))
+		return;
+
+	#ifdef CONFIG_DEBUG_CORE
+	cout<<"setMessageTagObjectHandler "<<MESSAGE_TAGS[tag]<<" to "<<object<<endl;
+	#endif
+
+	#ifdef ASSERT
+	assert(m_plugins.count(plugin)>0);
+	assert(m_plugins[plugin].hasMessageTag(tag));
+	#endif
+
+	m_messageTagExecutor.setObjectHandler(tag,object);
+
+	m_plugins[plugin].addRegisteredMessageTagHandler(tag);
+}
+
+
+/**
+ * runWithProfiler if -run-profiler is provided
+ * otherwise, run runVanilla()
+ */
+void ComputeCore::run(){
+
+	// ask the router if it is enabled
+	// the virtual router will disable itself if there were
+	// problems during configuration
+	m_routerIsEnabled=m_router.isEnabled();
+
+	if(!m_resolvedSymbols)
+		resolveSymbols();
+
+	if(m_hasFatalErrors){
+		cout<<"Exiting because of previously reported errors."<<endl;
+		return;
+	}
+
+	m_startingTimeMicroseconds = getMicroseconds();
+
+	if(m_routerIsEnabled)
+		m_router.getGraph()->start(m_rank);
+
+	if(m_runProfiler){
+		runWithProfiler();
+	}else{
+		runVanilla();
+	}
+
+	if(m_routerIsEnabled)
+		m_router.getGraph()->printStatus();
+
+}
+
+/**
+ * the while loop is *the* main loop of Ray for each 
+ * processor.
+ * it is similar to the main loop of a video game, actually, but without a display.
+ */
+void ComputeCore::runVanilla(){
+
+	#ifdef CONFIG_DEBUG_CORE
+	cout<<"m_alive= "<<m_alive<<endl;
+	#endif
+
+	while(m_alive || (m_routerIsEnabled && !m_router.hasCompletedRelayEvents())){
+		
+		// 1. receive the message (0 or 1 message is received)
+		// blazing fast, receives 0 or 1 message, never more, never less, other messages will wait for the next iteration !
+		receiveMessages(); 
+
+		// 2. process the received message, if any
+		// consume the one message received, if any, also very fast because it is done with an array mapping tags to function pointers
+		processMessages();
+
+		// 3. process data according to current slave and master modes
+		// should be fast, but apparently call_RAY_SLAVE_MODE_EXTENSION is slowish sometimes...
+		processData();
+
+		// 4. send messages
+		// fast, sends at most 17 messages. In most case it is either 0 or 1 message.,..
+		sendMessages();
+	}
+
+	#ifdef CONFIG_DEBUG_CORE
+	cout<<"m_alive= "<<m_alive<<endl;
+	#endif
+}
+
+/*
+ * This is the main loop of the program.
+ * One instance on each MPI rank.
+ */
+void ComputeCore::runWithProfiler(){
+	// define some variables that hold life statistics of this
+	// MPI rank
+	int ticks=0;
+	int sentMessages=0;
+	int sentMessagesInProcessMessages=0;
+	int sentMessagesInProcessData=0;
+	int receivedMessages=0;
+	map<int,int> receivedTags;
+	map<int,int> sentTagsInProcessMessages;
+	map<int,int> sentTagsInProcessData;
+	
+	int resolution=100;// milliseconds
+	int parts=1000/resolution;
+
+	uint64_t startingTime=getMilliSeconds();
+
+	uint64_t lastTime=getMilliSeconds();
+
+/*
+	uint64_t lastTickWhenSentMessageInProcessMessage=lastTime;
+	uint64_t lastTickWhenSentMessageInProcessData=lastTime;
+*/
+
+	vector<int> distancesForProcessMessages;
+	vector<int> distancesForProcessData;
+
+	bool profilerVerbose=m_profilerVerbose; 
+
+	while(m_alive  || (m_routerIsEnabled && !m_router.hasCompletedRelayEvents())){
+		uint64_t t=getMilliSeconds();
+		if(t>=(lastTime+resolution)/parts*parts){
+
+			double seconds=(t-startingTime)/1000.0;
+
+			int balance=sentMessages-receivedMessages;
+
+			if(profilerVerbose){
+				printf("Rank %i: %s Time= %.2f s Speed= %i Sent= %i (processMessages: %i, processData: %i) Received= %i Balance= %i\n",
+					m_rank,SLAVE_MODES[m_switchMan.getSlaveMode()],
+					seconds,ticks,sentMessages,sentMessagesInProcessMessages,sentMessagesInProcessData,
+					receivedMessages,balance);
+				fflush(stdout);
+
+				m_profiler.printGranularities(m_rank);
+			}
+
+			m_profiler.clearGranularities();
+
+			if(receivedTags.size() > 0 && profilerVerbose){
+				cout<<"Rank "<<m_messagesHandler.getRank()<<" received in receiveMessages:"<<endl;
+				for(map<int,int>::iterator i=receivedTags.begin();i!=receivedTags.end();i++){
+					int tag=i->first;
+					int count=i->second;
+					cout<<"Rank "<<m_messagesHandler.getRank()<<"        "<<MESSAGE_TAGS[tag]<<"	"<<count<<endl;
+				}
+			}
+
+			if(sentTagsInProcessMessages.size() > 0 && profilerVerbose){
+				cout<<"Rank "<<m_messagesHandler.getRank()<<" sent in processMessages:"<<endl;
+				for(map<int,int>::iterator i=sentTagsInProcessMessages.begin();i!=sentTagsInProcessMessages.end();i++){
+					int tag=i->first;
+					int count=i->second;
+					cout<<"Rank "<<m_messagesHandler.getRank()<<"        "<<MESSAGE_TAGS[tag]<<"	"<<count<<endl;
+				}
+
+/*
+				int average1=getAverage(&distancesForProcessMessages);
+				int deviation1=getStandardDeviation(&distancesForProcessMessages);
+			
+				cout<<"Rank "<<m_messagesHandler.getRank()<<" distance between processMessages messages: average= "<<average1<<", stddev= "<<deviation1<<
+					", n= "<<distancesForProcessMessages.size()<<endl;
+				
+*/
+				#ifdef FULL_DISTRIBUTION
+				map<int,int> distribution1;
+				for(int i=0;i<(int)distancesForProcessMessages.size();i++){
+					distribution1[distancesForProcessMessages[i]]++;
+				}
+				cout<<"Rank "<<m_messagesHandler.getRank()<<" distribution: "<<endl;
+				for(map<int,int>::iterator i=distribution1.begin();i!=distribution1.end();i++){
+					cout<<i->first<<" "<<i->second<<endl;
+				}
+				#endif
+
+			}
+
+			distancesForProcessMessages.clear();
+
+			if(sentTagsInProcessData.size() > 0 && profilerVerbose){
+				cout<<"Rank "<<m_messagesHandler.getRank()<<" sent in processData:"<<endl;
+				for(map<int,int>::iterator i=sentTagsInProcessData.begin();i!=sentTagsInProcessData.end();i++){
+					int tag=i->first;
+					int count=i->second;
+					cout<<"Rank "<<m_messagesHandler.getRank()<<"        "<<MESSAGE_TAGS[tag]<<"	"<<count<<endl;
+				}
+/*
+				int average2=getAverage(&distancesForProcessData);
+				int deviation2=getStandardDeviation(&distancesForProcessData);
+	
+				cout<<"Rank "<<m_messagesHandler.getRank()<<" distance between processData messages: average= "<<average2<<", stddev= "<<deviation2<<
+					", n= "<<distancesForProcessData.size()<<endl;
+				
+*/
+				#ifdef FULL_DISTRIBUTION
+				map<int,int> distribution2;
+				for(int i=0;i<(int)distancesForProcessData.size();i++){
+					distribution2[distancesForProcessData[i]]++;
+				}
+				cout<<"Rank "<<m_messagesHandler.getRank()<<" distribution: "<<endl;
+				for(map<int,int>::iterator i=distribution2.begin();i!=distribution2.end();i++){
+					cout<<i->first<<" "<<i->second<<endl;
+				}
+				#endif
+
+			}
+
+			distancesForProcessData.clear();
+
+			sentMessages=0;
+			sentMessagesInProcessMessages=0;
+			sentMessagesInProcessData=0;
+			receivedMessages=0;
+			receivedTags.clear();
+			sentTagsInProcessMessages.clear();
+			sentTagsInProcessData.clear();
+			ticks=0;
+
+			lastTime=t;
+		}
+
+		/* collect some statistics for the profiler */
+
+		// 1. receive the message (0 or 1 message is received)
+		receiveMessages(); 
+		receivedMessages+=m_inbox.size();
+		
+		for(int i=0;i<(int)m_inbox.size();i++){
+			// stript routing information, if any
+			uint8_t tag=m_inbox[i]->getTag();
+			receivedTags[tag]++;
+		}
+
+		// 2. process the received message, if any
+		processMessages();
+
+		int messagesSentInProcessMessages=m_outbox.size();
+		sentMessagesInProcessMessages += messagesSentInProcessMessages;
+		sentMessages += messagesSentInProcessMessages;
+
+/*
+		if(messagesSentInProcessMessages > 0){
+			int distance=t- lastTickWhenSentMessageInProcessMessage;
+			lastTickWhenSentMessageInProcessMessage=t;
+			distancesForProcessMessages.push_back(distance);
+		}
+*/
+
+		// 3. process data according to current slave and master modes
+
+		int currentSlaveMode=m_switchMan.getSlaveMode();
+
+		uint64_t startingTime = getThreadMicroseconds();
+		processData();
+		uint64_t endingTime = getThreadMicroseconds();
+
+		int difference = endingTime - startingTime;
+		
+		m_profiler.addGranularity(currentSlaveMode,difference);
+
+		/* threshold to say something is taking too long */
+		/* in microseconds */
+		int tooLong=m_profiler.getThreshold();
+
+		if(difference >= tooLong){
+			cout<<"Warning, SlaveMode= "<<SLAVE_MODES[currentSlaveMode]<<" GranularityInMicroseconds= "<<difference<<""<<endl;
+			m_profiler.printStack();
+		}
+
+		m_profiler.resetStack();
+
+		int messagesSentInProcessData = m_outbox.size() - messagesSentInProcessMessages;
+		sentMessagesInProcessData += messagesSentInProcessData;
+		sentMessages += messagesSentInProcessData;
+
+		for(int i=0;i<messagesSentInProcessMessages;i++){
+			// stript routing information, if any
+			uint8_t tag=m_outbox[i]->getTag();
+			sentTagsInProcessMessages[tag]++;
+		}
+
+		for(int i=messagesSentInProcessMessages;i<(int)m_outbox.size();i++){
+			// stript routing information, if any
+			uint8_t tag=m_outbox[i]->getTag();
+			sentTagsInProcessData[tag]++;
+		}
+
+		// 4. send messages
+		sendMessages();
+
+		/* increment ticks */
+		ticks++;
+	}
+
+	m_profiler.printAllGranularities();
+}
+
+void ComputeCore::processMessages(){
+	#ifdef ASSERT
+	assert(m_inbox.size()>=0&&m_inbox.size()<=1);
+	#endif
+
+	if(m_inbox.size()==0)
+		return;
+
+
+	// if routing is enabled, we want to strip the routing tags if it
+	// is required
+	if(m_routerIsEnabled){
+		if(m_router.routeIncomingMessages()){
+			// if the message has routing tag, we don't need to process it...
+
+/*
+ * If a message is routed, the original message needs to be destroyed 
+ * with fire. Otherwise, a slave mode or a master mode will pick it up, 
+ * which will cause silly behaviors.
+ */
+			m_inbox.clear();
+
+			return;
+		}
+	}
+
+	Message*message=m_inbox[0];
+	MessageTag messageTag=message->getTag();
+
+	#ifdef ASSERT
+	assert(messageTag!=INVALID_HANDLE);
+	assert(m_allocatedMessageTags.count(messageTag)>0);
+	string symbol=MESSAGE_TAGS[messageTag];
+	assert(m_messageTagSymbols.count(symbol));
+	assert(m_messageTagSymbols[symbol]==messageTag);
+	#endif
+
+	// check if the tag is in the list of slave switches
+	m_switchMan.openSlaveModeLocally(messageTag,m_rank);
+
+	m_messageTagExecutor.callHandler(messageTag,message);
+}
+
+void ComputeCore::sendMessages(){
+	// assert that we did not overflow the ring
+	#ifdef ASSERT
+	if(m_outboxAllocator.getCount() > m_maximumAllocatedOutboxBuffers){
+		cout<<"Rank "<<m_rank<<" Error, allocated "<<m_outboxAllocator.getCount()<<" buffers, but maximum is ";
+		cout<<m_maximumAllocatedOutboxBuffers<<endl;
+		cout<<" outboxSize= "<<m_outbox.size()<<endl;
+		cout<<"This means that too many messages were created in this time slice."<<endl;
+	}
+
+	assert(m_outboxAllocator.getCount()<=m_maximumAllocatedOutboxBuffers);
+	m_outboxAllocator.resetCount();
+	int messagesToSend=m_outbox.size();
+	if(messagesToSend>m_maximumNumberOfOutboxMessages){
+		cout<<"Fatal: "<<messagesToSend<<" messages to send, but max is "<<m_maximumNumberOfOutboxMessages<<endl;
+		cout<<"tags=";
+		for(int i=0;i<(int)m_outbox.size();i++){
+			MessageTag tag=m_outbox[i]->getTag();
+			cout<<" "<<MESSAGE_TAGS[tag]<<" handle= "<<tag<<endl;
+		}
+		cout<<endl;
+	}
+
+	assert(messagesToSend<=m_maximumNumberOfOutboxMessages);
+	if(messagesToSend>m_maximumNumberOfOutboxMessages){
+		uint8_t tag=m_outbox[0]->getTag();
+		cout<<"Tag="<<tag<<" n="<<messagesToSend<<" max="<<m_maximumNumberOfOutboxMessages<<endl;
+	}
+
+	#endif
+
+	// route messages if the router is enabled
+	if(m_routerIsEnabled){
+		// if message routing is enabled,
+		// generate routing tags.
+		m_router.routeOutcomingMessages();
+	}
+
+	// parameters.showCommunicationEvents() 
+	if( m_showCommunicationEvents && m_outbox.size() > 0){
+		uint64_t microseconds=getMicroseconds() - m_startingTimeMicroseconds;
+		for(int i=0;i<(int)m_outbox.size();i++){
+			cout<<"[Communication] "<<microseconds<<" microseconds, SEND ";
+			m_outbox[i]->print();
+			cout<<endl;
+		}
+	}
+
+	for(int i=0;i<(int)m_outbox.size();i++){
+		m_tickLogger.logSendMessage(INVALID_HANDLE);
+	}
+
+	// add checksums if necessary
+	if(m_doChecksum){
+		addMessageChecksums();
+	}
+
+	// finally, send the messages
+	m_messagesHandler.sendMessages(&m_outbox,&m_outboxAllocator);
+}
+
+void ComputeCore::addMessageChecksums(){
+
+	int count=m_outbox.size();
+	for(int i=0;i<count;i++){
+		MessageUnit*data=m_outbox.at(i)->getBuffer();
+		int numberOfUnits=m_outbox.at(i)->getCount();
+
+		// don't compute checksum for empty messages
+		if(numberOfUnits==0){
+			continue;
+		}
+
+		int numberOfBytes=sizeof(MessageUnit)*numberOfUnits;
+
+		uint8_t*bytes=(uint8_t*)data;
+
+		uint32_t crc32=computeCyclicRedundancyCode32(bytes,numberOfBytes);
+
+		data[numberOfUnits]=crc32;
+
+		m_outbox.at(i)->setCount(numberOfUnits+1);
+	}
+
+}
+
+void ComputeCore::verifyMessageChecksums(){
+
+	int count=m_inbox.size();
+	for(int i=0;i<count;i++){
+		MessageUnit*data=m_inbox.at(i)->getBuffer();
+
+		// this contains the checksum unit too.
+		int numberOfUnits=m_inbox.at(i)->getCount();
+
+		// don't compute checksum for empty messages
+		if(numberOfUnits==0){
+			continue;
+		}
+
+		// the last MessageUnit contains the crc32.
+		// note that the CRC32 feature only works for MessageUnit at least
+		// 32 bits.
+		int numberOfBytes=sizeof(MessageUnit)*(numberOfUnits-1);
+
+		uint8_t*bytes=(uint8_t*)data;
+
+		// compute the checksum, excluding the reference checksum
+		// from the data
+		uint32_t crc32=computeCyclicRedundancyCode32(bytes,numberOfBytes);
+
+		uint32_t expectedChecksum=data[numberOfUnits-1];
+
+		#ifdef CONFIG_SHOW_CHECKSUM
+		cout<<" Expected checksum (CRC32): "<<hex<<expectedChecksum<<endl;
+		cout<<" Actual checksum (CRC32): "<<hex<<crc32<<dec<<endl;
+		#endif
+
+		if(crc32 != expectedChecksum){
+			Message*message=m_inbox.at(i);
+			cout<<"Error: RayPlatform detected a message corruption !"<<endl;
+			cout<<" Tag: "<<MESSAGE_TAGS[message->getTag()]<<endl;
+			cout<<" Source: "<<message->getSource()<<endl;
+			cout<<" Destination: "<<message->getDestination()<<endl;
+			cout<<" sizeof(MessageUnit): "<<sizeof(MessageUnit)<<endl;
+			cout<<" Count (excluding checksum): "<<numberOfUnits-1<<endl;
+			cout<<" Expected checksum (CRC32): "<<hex<<expectedChecksum<<endl;
+			cout<<" Actual checksum (CRC32): "<<hex<<crc32<<dec<<endl;
+		}
+
+		#ifdef ASSERT
+		assert(numberOfUnits>=2);
+		#endif
+
+		// remove the checksum
+		m_inbox.at(i)->setCount(numberOfUnits-1);
+
+		#ifdef ASSERT
+		assert(numberOfUnits>=1);
+		#endif
+	}
+
+}
+
+/**
+ * receivedMessages receives 0 or 1 messages.
+ * If more messages are available to be pumped, they will wait until the
+ * next ComputeCore cycle.
+ */
+void ComputeCore::receiveMessages(){
+	m_inbox.clear();
+	m_messagesHandler.receiveMessages(&m_inbox,&m_inboxAllocator);
+
+	// verify checksums and remove them
+	if(m_doChecksum){
+		verifyMessageChecksums();
+	}
+
+	for(int i=0;i<(int)m_inbox.size();i++){
+		m_tickLogger.logReceivedMessage(INVALID_HANDLE);
+	}
+
+	#ifdef ASSERT
+	int receivedMessages=m_inbox.size();
+	assert(receivedMessages<=m_maximumNumberOfInboxMessages);
+	#endif
+
+	if(m_inbox.size() > 0 && m_showCommunicationEvents){
+		uint64_t theTime=getMicroseconds();
+		uint64_t microseconds=theTime - m_startingTimeMicroseconds;
+		for(int i=0;i<(int)m_inbox.size();i++){
+			cout<<"[Communication] "<<microseconds<<" microseconds, RECEIVE ";
+			m_inbox[i]->print();
+			cout<<endl;
+		}
+	}
+}
+
+/** process data my calling current slave and master methods */
+void ComputeCore::processData(){
+
+	// call the master method first
+	MasterMode master=m_switchMan.getMasterMode();
+
+	#ifdef RayPlatform_ASSERT
+	assert(master!=INVALID_HANDLE);
+	assert(m_allocatedMasterModes.count(master)>0);
+	string masterSymbol=MASTER_MODES[master];
+	assert(m_masterModeSymbols.count(masterSymbol)>0);
+	assert(m_masterModeSymbols[masterSymbol]==master);
+	#endif
+
+	#ifdef CONFIG_DEBUG_processData
+	cout<<"master mode -> "<<MASTER_MODES[master]<<" handle is "<<master<<endl;
+	#endif
+
+	m_masterModeExecutor.callHandler(master);
+	m_tickLogger.logMasterTick(master);
+
+	// then call the slave method
+	SlaveMode slave=m_switchMan.getSlaveMode();
+
+	#ifdef RayPlatform_ASSERT
+	assert(slave!=INVALID_HANDLE);
+	assert(m_allocatedSlaveModes.count(slave)>0);
+	string slaveSymbol=SLAVE_MODES[slave];
+	assert(m_slaveModeSymbols.count(slaveSymbol)>0);
+	assert(m_slaveModeSymbols[slaveSymbol]==slave);
+	#endif
+
+	#ifdef CONFIG_DEBUG_processData
+	cout<<"slave mode -> "<<SLAVE_MODES[slave]<<" handle is "<<slave<<endl;
+	#endif
+
+	m_slaveModeExecutor.callHandler(slave);
+	m_tickLogger.logSlaveTick(slave);
+}
+
+void ComputeCore::constructor(int*argc,char***argv){
+
+	m_doChecksum=false;
+
+	// checksum calculation is only tested
+	// for cases with sizeof(MessageUnit)>=4 bytes
+
+	const char verifyMessages[]="-verify-message-integrity";
+	const char router[]="-route-messages";
+
+	m_routerIsEnabled=false;
+
+	int match=0;
+
+	for(int i=0;i<(*argc);i++){
+		if(strcmp( ((*argv)[i]), verifyMessages) == match){
+			m_doChecksum=true;
+		}else if(strcmp( ((*argv)[i]),router) == match){
+			m_routerIsEnabled=true;
+		}
+	}
+
+	m_argumentCount=*argc;
+	m_argumentValues=*argv;
+
+
+	m_resolvedSymbols=false;
+
+	m_hasFatalErrors=false;
+
+	m_firstRegistration=true;
+
+	m_hasFirstMode=false;
+
+	srand(portableProcessId() * getMicroseconds());
+
+	m_alive=true;
+
+	m_messagesHandler.constructor(argc,argv);
+
+	m_runProfiler=false;
+	m_showCommunicationEvents=false;
+	m_profilerVerbose=false;
+
+	m_rank=m_messagesHandler.getRank();
+	m_size=m_messagesHandler.getSize();
+
+	if(m_doChecksum){
+		cout<<"[RayPlatform] Rank "<<m_rank<<" will compute a CRC32 checksum for any non-empty message."<<" ("<<verifyMessages<<")"<<endl;
+	}
+
+	// set the number of buffers to use
+	int minimumNumberOfBuffers=128;
+
+	int availableBuffers=minimumNumberOfBuffers;
+
+	// even a message with a NULL buffer requires a buffer for routing
+	if(m_routerIsEnabled)
+		availableBuffers=m_size*2;
+
+	// this will occur when using the virtual router with a few processes
+	if(availableBuffers<minimumNumberOfBuffers)
+		availableBuffers=minimumNumberOfBuffers;
+
+
+	m_switchMan.constructor(m_rank,m_size);
+
+	m_virtualCommunicator.constructor(m_rank,m_size,&m_outboxAllocator,&m_inbox,&m_outbox);
+
+	/***********************************************************************************/
+	/** initialize the VirtualProcessor */
+	m_virtualProcessor.constructor(&m_outbox,&m_inbox,&m_outboxAllocator,
+		&m_virtualCommunicator);
+
+	m_maximumAllocatedInboxBuffers=1;
+	m_maximumAllocatedOutboxBuffers=availableBuffers;
+	
+	m_maximumNumberOfInboxMessages=1;
+	m_maximumNumberOfOutboxMessages=availableBuffers;
+
+	// broadcasting messages
+	// this case will occur when the number of requested outbox buffers is < the number of processor cores.
+	if(m_maximumNumberOfOutboxMessages < m_size){
+		m_maximumNumberOfOutboxMessages=m_size;
+	}
+
+	getInbox()->constructor(m_maximumNumberOfInboxMessages,"RAY_MALLOC_TYPE_INBOX_VECTOR",false);
+	
+	#if 0
+	cout<<"[ComputeCore] the inbox capacity is "<<m_maximumNumberOfInboxMessages<<" message"<<endl;
+	#endif
+
+	getOutbox()->constructor(m_maximumNumberOfOutboxMessages,"RAY_MALLOC_TYPE_OUTBOX_VECTOR",false);
+
+	#if 0
+	cout<<"[ComputeCore] the outbox capacity is "<<m_maximumNumberOfOutboxMessages<<" message"<<endl;
+	#endif
+
+	int maximumMessageSizeInByte=MAXIMUM_MESSAGE_SIZE_IN_BYTES;
+
+	// add a message unit to store the checksum or the routing information
+	// with 64-bit integers as MessageUnit, this is 4008 bytes or 501 MessageUnit maximum
+	// TODO: RayPlatform can not do both routing and checksums 
+	if(m_doChecksum || m_routerIsEnabled){
+		if(sizeof(MessageUnit)>=4){
+			maximumMessageSizeInByte+=sizeof(MessageUnit);
+		}else if(sizeof(MessageUnit)>=2){
+			maximumMessageSizeInByte+=2*sizeof(MessageUnit);
+		}else{
+			maximumMessageSizeInByte+=4*sizeof(MessageUnit);
+		}
+	}
+
+	m_inboxAllocator.constructor(m_maximumAllocatedInboxBuffers,
+		maximumMessageSizeInByte,
+		"RAY_MALLOC_TYPE_INBOX_ALLOCATOR",false);
+
+	#if 0
+	cout<<"[ComputeCore] allocated "<<m_maximumAllocatedInboxBuffers<<" buffers of size "<<maximumMessageSizeInByte<<" for inbox messages"<<endl;
+	#endif
+
+	m_outboxAllocator.constructor(m_maximumAllocatedOutboxBuffers,
+		maximumMessageSizeInByte,
+		"RAY_MALLOC_TYPE_OUTBOX_ALLOCATOR",false);
+
+	#if 0
+	cout<<"[ComputeCore] allocated "<<m_maximumAllocatedOutboxBuffers<<" buffers of size "<<maximumMessageSizeInByte<<" for outbox messages"<<endl;
+	#endif
+
+	for(int i=0;i<MAXIMUM_NUMBER_OF_MASTER_HANDLERS;i++){
+		strcpy(MASTER_MODES[i],"UnnamedMasterMode");
+	}
+	for(int i=0;i<MAXIMUM_NUMBER_OF_SLAVE_HANDLERS;i++){
+		strcpy(SLAVE_MODES[i],"UnnamedSlaveMode");
+	}
+	for(int i=0;i<MAXIMUM_NUMBER_OF_TAG_HANDLERS;i++){
+		strcpy(MESSAGE_TAGS[i],"UnnamedMessageTag");
+	}
+
+	m_currentSlaveModeToAllocate=0;
+	m_currentMasterModeToAllocate=0;
+	m_currentMessageTagToAllocate=0;
+
+}
+
+void ComputeCore::enableProfiler(){
+	m_runProfiler=true;
+}
+
+void ComputeCore::showCommunicationEvents(){
+	m_showCommunicationEvents=true;
+}
+
+void ComputeCore::enableProfilerVerbosity(){
+	m_profilerVerbose=true;
+}
+
+MessagesHandler*ComputeCore::getMessagesHandler(){
+	return &m_messagesHandler;
+}
+
+Profiler*ComputeCore::getProfiler(){
+	return &m_profiler;
+}
+
+TickLogger*ComputeCore::getTickLogger(){
+	return &m_tickLogger;
+}
+
+SwitchMan*ComputeCore::getSwitchMan(){
+	return &m_switchMan;
+}
+
+StaticVector*ComputeCore::getOutbox(){
+	return &m_outbox;
+}
+
+StaticVector*ComputeCore::getInbox(){
+	return &m_inbox;
+}
+
+MessageRouter*ComputeCore::getRouter(){
+	return &m_router;
+}
+
+RingAllocator*ComputeCore::getOutboxAllocator(){
+	return &m_outboxAllocator;
+}
+
+RingAllocator*ComputeCore::getInboxAllocator(){
+	return &m_inboxAllocator;
+}
+
+bool*ComputeCore::getLife(){
+	return &m_alive;
+}
+
+VirtualProcessor*ComputeCore::getVirtualProcessor(){
+	return &m_virtualProcessor;
+}
+
+VirtualCommunicator*ComputeCore::getVirtualCommunicator(){
+	return &m_virtualCommunicator;
+}
+
+void ComputeCore::registerPlugin(CorePlugin*plugin){
+	
+	if(m_firstRegistration){
+
+		m_firstRegistration=false;
+
+		// register some built-in plugins
+
+		registerPlugin(&m_switchMan);
+
+	}
+
+	m_listOfPlugins.push_back(plugin);
+
+	plugin->registerPlugin(this);
+}
+
+void ComputeCore::resolveSymbols(){
+	if(m_resolvedSymbols)
+		return;
+
+	registerPlugin(&m_messagesHandler); // must be the last registered
+
+	for(int i=0;i<(int)m_listOfPlugins.size();i++){
+		CorePlugin*plugin=m_listOfPlugins[i];
+		plugin->resolveSymbols(this);
+	}
+
+	m_resolvedSymbols=true;
+}
+
+void ComputeCore::destructor(){
+	getMessagesHandler()->destructor();
+}
+
+void ComputeCore::stop(){
+	m_alive=false;
+}
+
+void ComputeCore::setSlaveModeSymbol(PluginHandle plugin,SlaveMode mode,const char*symbol){
+	if(!validationPluginAllocated(plugin))
+		return;
+	
+	if(!validationSlaveModeRange(plugin,mode))
+		return;
+
+	if(!validationSlaveModeOwnership(plugin,mode)){
+		cout<<"was trying to set symbol "<<symbol<<" to mode "<<mode<<endl;
+		return;
+	}
+
+	if(!validationSlaveModeSymbolAvailable(plugin,symbol)){
+		return;
+	}
+
+	if(!validationSlaveModeSymbolNotRegistered(plugin,mode))
+		return;
+
+	if(!validationSlaveModeRange(plugin,mode))
+		return;
+
+	#ifdef ASSERT
+	assert(mode>=0);
+	assert(mode<MAXIMUM_NUMBER_OF_SLAVE_HANDLERS);
+	#endif
+
+	#ifdef ASSERT
+	assert(m_plugins.count(plugin)>0);
+	assert(m_plugins[plugin].hasSlaveMode(mode));
+	#endif
+
+	strcpy(SLAVE_MODES[mode],symbol);
+
+	m_plugins[plugin].addRegisteredSlaveModeSymbol(mode);
+
+	m_registeredSlaveModeSymbols.insert(mode);
+
+	m_slaveModeSymbols[symbol]=mode;
+
+	#ifdef CONFIG_DEBUG_SLAVE_SYMBOLS
+	cout<<"Registered slave mode "<<mode<<" to symbol "<<symbol<<endl;
+	#endif
+}
+
+void ComputeCore::setMasterModeSymbol(PluginHandle plugin,MasterMode mode,const char*symbol){
+	
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMasterModeRange(plugin,mode))
+		return;
+
+	if(!validationMasterModeOwnership(plugin,mode))
+		return;
+
+	if(!validationMasterModeSymbolAvailable(plugin,symbol)){
+		return;
+	}
+
+	if(!validationMasterModeSymbolNotRegistered(plugin,mode))
+		return;
+
+	if(!validationMasterModeRange(plugin,mode))
+		return;
+
+	#ifdef ASSERT
+	assert(mode>=0);
+	assert(mode<MAXIMUM_NUMBER_OF_MASTER_HANDLERS);
+	#endif
+
+	#ifdef ASSERT
+	assert(m_plugins.count(plugin)>0);
+	assert(m_plugins[plugin].hasMasterMode(mode));
+	#endif
+
+	strcpy(MASTER_MODES[mode],symbol);
+
+	m_plugins[plugin].addRegisteredMasterModeSymbol(mode);
+
+	m_registeredMasterModeSymbols.insert(mode);
+
+	m_masterModeSymbols[symbol]=mode;
+}
+
+void ComputeCore::setMessageTagSymbol(PluginHandle plugin,MessageTag tag,const char*symbol){
+
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMessageTagRange(plugin,tag))
+		return;
+
+	if(!validationMessageTagOwnership(plugin,tag))
+		return;
+
+	if(!validationMessageTagSymbolAvailable(plugin,symbol))
+		return;
+
+	if(!validationMessageTagSymbolNotRegistered(plugin,tag))
+		return;
+
+	if(!validationMessageTagRange(plugin,tag))
+		return;
+
+	#ifdef ASSERT
+	assert(tag>=0);
+	assert(tag<MAXIMUM_NUMBER_OF_TAG_HANDLERS);
+	#endif
+
+	#ifdef ASSERT
+	assert(m_plugins.count(plugin)>0);
+	assert(m_plugins[plugin].hasMessageTag(tag));
+	#endif
+
+	strcpy(MESSAGE_TAGS[tag],symbol);
+
+	m_plugins[plugin].addRegisteredMessageTagSymbol(tag);
+
+	m_registeredMessageTagSymbols.insert(tag);
+
+	m_messageTagSymbols[symbol]=tag;
+}
+
+PluginHandle ComputeCore::allocatePluginHandle(){
+	PluginHandle handle=generatePluginHandle();
+	
+	while(m_plugins.count(handle)>0){
+		handle=generatePluginHandle();
+	}
+
+	RegisteredPlugin plugin;
+
+	m_plugins[handle]=plugin;
+
+	return handle;
+}
+
+SlaveMode ComputeCore::allocateSlaveModeHandle(PluginHandle plugin){
+
+	if(!validationPluginAllocated(plugin))
+		return INVALID_HANDLE;
+
+
+	#ifdef ASSERT
+	assert(m_plugins.count(plugin)>0);
+	#endif
+
+	SlaveMode handle=m_currentSlaveModeToAllocate;
+
+	if(!(0<=handle && handle<MAXIMUM_NUMBER_OF_SLAVE_HANDLERS))
+		handle=m_currentSlaveModeToAllocate;
+
+	while(m_allocatedSlaveModes.count(handle)>0){
+		handle=m_currentSlaveModeToAllocate++;
+	}
+
+	if(!validationSlaveModeRange(plugin,handle))
+		return INVALID_HANDLE;
+
+	#ifdef ASSERT
+	assert(m_allocatedSlaveModes.count(handle)==0);
+	#endif
+
+	m_allocatedSlaveModes.insert(handle);
+
+	m_plugins[plugin].addAllocatedSlaveMode(handle);
+
+	#ifdef ASSERT
+	assert(m_allocatedSlaveModes.count(handle)>0);
+	assert(m_plugins[plugin].hasSlaveMode(handle));
+	#endif
+	
+	return handle;
+}
+
+MasterMode ComputeCore::allocateMasterModeHandle(PluginHandle plugin){
+
+	if(!validationPluginAllocated(plugin))
+		return INVALID_HANDLE;
+
+	#ifdef ASSERT
+	assert(m_plugins.count(plugin)>0);
+	#endif
+
+	MasterMode handle=m_currentMasterModeToAllocate;
+
+	if(!(0<=handle && handle<MAXIMUM_NUMBER_OF_MASTER_HANDLERS))
+		handle=m_currentMasterModeToAllocate;
+
+	while(m_allocatedMasterModes.count(handle)>0){
+		handle=m_currentMasterModeToAllocate++;
+	}
+
+	if(!validationMasterModeRange(plugin,handle))
+		return INVALID_HANDLE;
+
+	#ifdef ASSERT
+	assert(m_allocatedMasterModes.count(handle)==0);
+	#endif
+
+	m_allocatedMasterModes.insert(handle);
+
+	m_plugins[plugin].addAllocatedMasterMode(handle);
+
+	#ifdef ASSERT
+	assert(m_allocatedMasterModes.count(handle)>0);
+	assert(m_plugins[plugin].hasMasterMode(handle));
+	#endif
+
+	return handle; 
+}
+
+MessageTag ComputeCore::allocateMessageTagHandle(PluginHandle plugin){
+
+	if(!validationPluginAllocated(plugin))
+		return INVALID_HANDLE;
+
+	#ifdef ASSERT
+	assert(m_plugins.count(plugin)>0);
+	#endif
+
+	MessageTag handle=m_currentMessageTagToAllocate;
+
+	if(!(0<=handle && handle < MAXIMUM_NUMBER_OF_TAG_HANDLERS))
+		handle=m_currentMessageTagToAllocate;
+
+	while(m_allocatedMessageTags.count(handle)>0){
+		handle=m_currentMessageTagToAllocate++;
+	}
+
+	if(!validationMessageTagRange(plugin,handle))
+		return INVALID_HANDLE;
+
+	#ifdef ASSERT
+	assert(m_allocatedMessageTags.count(handle)==0);
+	#endif
+
+	m_allocatedMessageTags.insert(handle);
+
+	m_plugins[plugin].addAllocatedMessageTag(handle);
+
+	#ifdef ASSERT
+	assert(m_allocatedMessageTags.count(handle)>0);
+	assert(m_plugins[plugin].hasMessageTag(handle));
+	#endif
+
+	return handle;
+}
+
+PluginHandle ComputeCore::generatePluginHandle(){
+	uint64_t randomNumber=rand();
+
+	return uniform_hashing_function_1_64_64(randomNumber);
+}
+
+bool ComputeCore::validationPluginAllocated(PluginHandle plugin){
+	if(!m_plugins.count(plugin)>0){
+		cout<<"Error, plugin "<<plugin<<" is not allocated"<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationSlaveModeOwnership(PluginHandle plugin,SlaveMode handle){
+	if(!m_plugins[plugin].hasSlaveMode(handle)){
+		cout<<"Error, plugin "<<m_plugins[plugin].getPluginName();
+		setFatalError();
+		cout<<" ("<<plugin<<") has no ownership on slave mode "<<handle<<endl;
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationMasterModeOwnership(PluginHandle plugin,MasterMode handle){
+	if(!m_plugins[plugin].hasMasterMode(handle)){
+		cout<<"Error, plugin "<<m_plugins[plugin].getPluginName();
+		cout<<" ("<<plugin<<") has no ownership on master mode "<<handle<<endl;
+		cout<<" public symbol is "<<MASTER_MODES[handle]<<endl;
+		setFatalError();
+
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationMessageTagOwnership(PluginHandle plugin,MessageTag handle){
+	if(!m_plugins[plugin].hasMessageTag(handle)){
+		cout<<"Error, plugin "<<m_plugins[plugin].getPluginName();
+		cout<<" ("<<plugin<<") has no ownership on message tag mode "<<handle<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+void ComputeCore::setPluginName(PluginHandle plugin,const char*name){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	m_plugins[plugin].setPluginName(name);
+}
+
+void ComputeCore::printPlugins(string directory){
+
+/*
+	ostringstream list;
+	list<<directory<<"/list.txt";
+
+	ofstream f1(list.str().c_str());
+
+	for(map<PluginHandle,RegisteredPlugin>::iterator i=m_plugins.begin();
+		i!=m_plugins.end();i++){
+		
+		f1<<i->first<<"	plugin_"<<i->second.getPluginName()<<endl;
+	}
+
+	f1.close();
+*/
+
+	for(map<PluginHandle,RegisteredPlugin>::iterator i=m_plugins.begin();
+		i!=m_plugins.end();i++){
+
+		ostringstream file;
+		file<<directory<<"/plugin_"<<i->second.getPluginName()<<".txt";
+
+		ofstream f2(file.str().c_str());
+		i->second.print(&f2);
+		f2.close();
+	}
+
+}
+
+SlaveMode ComputeCore::getSlaveModeFromSymbol(PluginHandle plugin,const char*symbol){
+	if(!validationPluginAllocated(plugin))
+		return INVALID_HANDLE;
+
+	if(!validationSlaveModeSymbolRegistered(plugin,symbol))
+		return INVALID_HANDLE;
+
+	string key=symbol;
+
+	if(m_slaveModeSymbols.count(key)>0){
+		SlaveMode handle=m_slaveModeSymbols[key];
+		
+		m_plugins[plugin].addResolvedSlaveMode(handle);
+
+		#ifdef CONFIG_DEBUG_SLAVE_SYMBOLS
+		cout<<"Plugin "<<m_plugins[plugin].getPluginName()<<" resolved symbol "<<symbol<<" to slave mode "<<handle<<endl;
+		#endif
+
+		return handle;
+	}
+
+	cout<<"Invalid handle returned!"<<endl;
+	return INVALID_HANDLE;
+}
+
+MasterMode ComputeCore::getMasterModeFromSymbol(PluginHandle plugin,const char*symbol){
+
+	if(!validationPluginAllocated(plugin))
+		return INVALID_HANDLE;
+
+	if(!validationMasterModeSymbolRegistered(plugin,symbol))
+		return INVALID_HANDLE;
+
+	string key=symbol;
+
+	if(m_masterModeSymbols.count(key)>0){
+		MasterMode handle=m_masterModeSymbols[key];
+
+		m_plugins[plugin].addResolvedMasterMode(handle);
+
+		#ifdef CONFIG_DEBUG_MASTER_SYMBOLS
+		cout<<"symbol "<<symbol<<" is resolved as master mode "<<handle<<endl;
+		#endif
+
+		return handle;
+	}
+
+	return INVALID_HANDLE;
+}
+
+MessageTag ComputeCore::getMessageTagFromSymbol(PluginHandle plugin,const char*symbol){
+
+	if(!validationPluginAllocated(plugin))
+		return INVALID_HANDLE;
+
+	if(!validationMessageTagSymbolRegistered(plugin,symbol))
+		return INVALID_HANDLE;
+
+	string key=symbol;
+
+	if(m_messageTagSymbols.count(key)>0){
+		MessageTag handle=m_messageTagSymbols[key];
+
+		m_plugins[plugin].addResolvedMessageTag(handle);
+
+		#ifdef CONFIG_DEBUG_TAG_SYMBOLS
+		cout<<" symbol "<<symbol<<" is resolved as message tag handle "<<handle<<endl;
+		#endif
+
+		return handle;
+	}
+
+	return INVALID_HANDLE;
+}
+
+bool ComputeCore::validationMessageTagSymbolAvailable(PluginHandle plugin,const char*symbol){
+	string key=symbol;
+
+	if(m_messageTagSymbols.count(key)>0){
+		cout<<"Error, plugin "<<plugin<<" can not register symbol "<<symbol<<" because it is already registered."<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationSlaveModeSymbolAvailable(PluginHandle plugin,const char*symbol){
+
+	string key=symbol;
+
+	if(m_slaveModeSymbols.count(key)>0){
+		cout<<"Error, plugin "<<plugin<<" can not register symbol "<<symbol<<" because it is already registered."<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+
+}
+
+bool ComputeCore::validationMasterModeSymbolAvailable(PluginHandle plugin,const char*symbol){
+
+	string key=symbol;
+
+	if(m_masterModeSymbols.count(key)>0){
+		cout<<"Error, plugin "<<plugin<<" can not register symbol "<<symbol<<" because it is already registered."<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationMessageTagSymbolRegistered(PluginHandle plugin,const char*symbol){
+	string key=symbol;
+
+	if(m_messageTagSymbols.count(key)==0){
+		cout<<"Error, plugin "<<plugin<<" (name: "<<m_plugins[plugin].getPluginName()<<") can not fetch symbol "<<symbol<<" because it is not registered."<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationSlaveModeSymbolRegistered(PluginHandle plugin,const char*symbol){
+
+	string key=symbol;
+
+	if(m_slaveModeSymbols.count(key)==0){
+		cout<<"Error, plugin "<<plugin<<" (name: "<<m_plugins[plugin].getPluginName()<<") can not fetch symbol "<<symbol<<" because it is not registered."<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+
+}
+
+bool ComputeCore::validationMasterModeSymbolRegistered(PluginHandle plugin,const char*symbol){
+
+	string key=symbol;
+
+	if(m_masterModeSymbols.count(key)==0){
+		cout<<"Error, plugin "<<plugin<<" (name: "<<m_plugins[plugin].getPluginName()<<") can not fetch symbol "<<symbol<<" because it is not registered."<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationMessageTagSymbolNotRegistered(PluginHandle plugin,MessageTag handle){
+
+	if(m_registeredMessageTagSymbols.count(handle)>0){
+		cout<<"Error, plugin "<<plugin<<" can not register symbol for message tag "<<handle <<" because it already has a symbol."<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationSlaveModeSymbolNotRegistered(PluginHandle plugin,SlaveMode handle){
+
+	if(m_registeredSlaveModeSymbols.count(handle)>0){
+		cout<<"Error, plugin "<<plugin<<" can not register symbol for slave mode "<<handle <<" because it already has a symbol."<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+
+}
+
+bool ComputeCore::validationMasterModeSymbolNotRegistered(PluginHandle plugin,MasterMode handle){
+
+	if(m_registeredMasterModeSymbols.count(handle)>0){
+		cout<<"Error, plugin "<<plugin<<" can not register symbol for master mode "<<handle <<" because it already has a symbol."<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+void ComputeCore::setPluginDescription(PluginHandle plugin,const char*a){
+
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	m_plugins[plugin].setPluginDescription(a);
+}
+
+void ComputeCore::setMasterModeToMessageTagSwitch(PluginHandle plugin,MasterMode mode,MessageTag tag){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMasterModeRange(plugin,mode))
+		return;
+
+	if(!validationMasterModeOwnership(plugin,mode))
+		return;
+
+	m_switchMan.addMasterSwitch(mode,tag);
+
+	m_plugins[plugin].addRegisteredMasterModeToMessageTagSwitch(mode);
+}
+
+void ComputeCore::setPluginAuthors(PluginHandle plugin,const char*text){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	m_plugins[plugin].setPluginAuthors(text);
+}
+
+void ComputeCore::setPluginLicense(PluginHandle plugin,const char*text){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	m_plugins[plugin].setPluginLicense(text);
+
+}
+
+void ComputeCore::setMessageTagToSlaveModeSwitch(PluginHandle plugin,MessageTag tag,SlaveMode mode){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMessageTagRange(plugin,tag))
+		return;
+
+	if(!validationMessageTagOwnership(plugin,tag))
+		return;
+
+	m_switchMan.addSlaveSwitch(tag,mode);
+
+	m_plugins[plugin].addRegisteredMessageTagToSlaveModeSwitch(tag);
+
+}
+
+void ComputeCore::setMessageTagReplyMessageTag(PluginHandle plugin,MessageTag tag,MessageTag reply){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMessageTagRange(plugin,tag))
+		return;
+
+	if(!validationMessageTagRange(plugin,reply))
+		return;
+
+	if(!validationMessageTagOwnership(plugin,tag))
+		return;
+
+	m_virtualCommunicator.setReplyType(tag,reply);
+
+	m_plugins[plugin].addRegisteredMessageTagReplyMessageTag(tag);
+}
+
+void ComputeCore::setMessageTagSize(PluginHandle plugin,MessageTag tag,int size){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMessageTagRange(plugin,tag))
+		return;
+
+	if(!validationMessageTagOwnership(plugin,tag))
+		return;
+
+	m_virtualCommunicator.setElementsPerQuery(tag,size);
+
+	m_plugins[plugin].addRegisteredMessageTagSize(tag);
+}
+
+void ComputeCore::setMasterModeNextMasterMode(PluginHandle plugin,MasterMode current,MasterMode next){
+
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMasterModeRange(plugin,current))
+		return;
+
+	if(!validationMasterModeRange(plugin,next))
+		return;
+
+	if(!validationMasterModeOwnership(plugin,current))
+		return;
+
+	m_switchMan.addNextMasterMode(current,next);
+
+	// configure the switch man
+	//
+	// this is where steps can be added or removed.
+
+	m_plugins[plugin].addRegisteredMasterModeNextMasterMode(current);
+}
+
+void ComputeCore::setFirstMasterMode(PluginHandle plugin,MasterMode mode){
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationMasterModeRange(plugin,mode))
+		return;
+
+	if(!validationMasterModeOwnership(plugin,mode))
+		return;
+
+	if(m_hasFirstMode)
+		cout<<"Error, already has a first master mode."<<endl;
+
+	m_hasFirstMode=true;
+
+	/** the computation will start there **/
+	if(m_rank == MASTER_RANK){
+		m_switchMan.setMasterMode(mode);
+	}
+
+	m_plugins[plugin].addRegisteredFirstMasterMode(mode);
+}
+
+string ComputeCore::getRayPlatformVersion(){
+
+#ifndef RAYPLATFORM_VERSION
+#define RAYPLATFORM_VERSION "Unknown-RayPlatform-Version"
+#endif
+
+	return RAYPLATFORM_VERSION;
+}
+
+bool ComputeCore::validationMasterModeRange(PluginHandle plugin,MasterMode mode){
+	if(!(0<= mode && mode < MAXIMUM_NUMBER_OF_MASTER_HANDLERS)){
+		cout<<"Error, master mode "<<mode<<" is not in the allowed range."<<endl;
+		cout<<"MAXIMUM_NUMBER_OF_MASTER_HANDLERS= "<<MAXIMUM_NUMBER_OF_MASTER_HANDLERS<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationSlaveModeRange(PluginHandle plugin,SlaveMode mode){
+	if(!(0<= mode && mode < MAXIMUM_NUMBER_OF_SLAVE_HANDLERS)){
+		cout<<"Error, slave mode "<<mode<<" is not in the allowed range."<<endl;
+		cout<<"MAXIMUM_NUMBER_OF_SLAVE_HANDLERS= "<<MAXIMUM_NUMBER_OF_SLAVE_HANDLERS<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationMessageTagRange(PluginHandle plugin,MessageTag tag){
+	if(!(0<= tag && tag < MAXIMUM_NUMBER_OF_TAG_HANDLERS)){
+		cout<<"Error, message tag "<<tag<<" is not in the allowed range."<<endl;
+		cout<<"MAXIMUM_NUMBER_OF_TAG_HANDLERS= "<<MAXIMUM_NUMBER_OF_TAG_HANDLERS<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+void ComputeCore::setFatalError(){
+	cout<<"A fatal error occurred !"<<endl;
+	m_hasFatalErrors=true;
+}
+
+void ComputeCore::sendEmptyMessageToAll(MessageTag tag){
+	m_switchMan.sendToAll(&m_outbox,m_rank,tag);
+}
+
+void ComputeCore::setObjectSymbol(PluginHandle plugin,void*object,const char* symbol){
+
+	if(!validationPluginAllocated(plugin))
+		return;
+
+	if(!validationObjectSymbolNotRegistered(plugin,symbol))
+		return;
+
+	int handle=m_objects.size();
+
+	m_objects.push_back(object);
+
+	m_objectSymbols[symbol]=handle;
+
+	m_plugins[plugin].addAllocatedObject(handle);
+	m_plugins[plugin].addRegisteredObjectSymbol(handle);
+}
+
+void* ComputeCore::getObjectFromSymbol(PluginHandle plugin,const char*symbol){
+
+	if(!validationPluginAllocated(plugin))
+		return NULL;
+
+	if(!validationObjectSymbolRegistered(plugin,symbol))
+		return NULL;
+
+	int handle=m_objectSymbols[symbol];
+
+	void*object=m_objects[handle];
+
+	m_plugins[plugin].addResolvedObject(handle);
+
+	return object;
+}
+
+bool ComputeCore::validationObjectSymbolRegistered(PluginHandle plugin,const char*symbol){
+
+	string key=symbol;
+
+	if(m_objectSymbols.count(key)==0){
+		cout<<"object symbol not registered, symbol: "<<symbol<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+bool ComputeCore::validationObjectSymbolNotRegistered(PluginHandle plugin,const char*symbol){
+
+	string key=symbol;
+
+	if(m_objectSymbols.count(key)>0){
+		cout<<"object symbol already registered, symbol: "<<symbol<<endl;
+		setFatalError();
+		return false;
+	}
+
+	return true;
+}
+
+int ComputeCore::getNumberOfArguments(){
+	return m_argumentCount;
+}
+
+char**ComputeCore::getArgumentValues(){
+	return m_argumentValues;
+}
diff --git a/RayPlatform/core/ComputeCore.h b/RayPlatform/core/ComputeCore.h
new file mode 100644
index 0000000..905806c
--- /dev/null
+++ b/RayPlatform/core/ComputeCore.h
@@ -0,0 +1,340 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _ComputeCore_h
+#define _ComputeCore_h
+
+#include <handlers/MessageTagHandler.h>
+#include <handlers/MessageTagExecutor.h>
+#include <handlers/SlaveModeHandler.h>
+#include <handlers/MasterModeHandler.h>
+#include <handlers/MasterModeExecutor.h>
+#include <handlers/SlaveModeExecutor.h>
+#include <communication/MessagesHandler.h>
+#include <profiling/Profiler.h>
+#include <structures/StaticVector.h>
+#include <communication/Message.h>
+#include <communication/MessageRouter.h>
+#include <profiling/TickLogger.h>
+#include <scheduling/SwitchMan.h>
+#include <memory/RingAllocator.h>
+#include <scheduling/VirtualProcessor.h>
+#include <communication/VirtualCommunicator.h>
+#include <plugins/CorePlugin.h>
+#include <plugins/RegisteredPlugin.h>
+#include <core/OperatingSystem.h>
+
+#include <iostream>
+#include <stdlib.h>
+#include <stdint.h>
+using namespace std;
+
+/** this class is a compute core
+ * to use it, you must set the handlers of your program
+ * using setMessageTagObjectHandler(), setSlaveModeObjectHandler(),
+ * and setMasterModeObjectHandler().
+ *
+ * after that, you simply have to call run()
+ *
+ * \author Sébastien Boisvert
+ */
+class ComputeCore{
+
+	int m_argumentCount;
+	char**m_argumentValues;
+
+	bool m_resolvedSymbols;
+	bool m_hasFatalErrors;
+	
+	bool m_hasFirstMode;
+	bool m_firstRegistration;
+
+	vector<CorePlugin*> m_listOfPlugins;
+
+	vector<void*> m_objects;
+
+	map<string,MasterMode> m_masterModeSymbols;
+	map<string,SlaveMode> m_slaveModeSymbols;
+	map<string,MessageTag> m_messageTagSymbols;
+	map<string,int> m_objectSymbols;
+
+	set<SlaveMode> m_allocatedSlaveModes;
+	set<MasterMode> m_allocatedMasterModes;
+	set<MessageTag> m_allocatedMessageTags;
+
+	set<SlaveMode> m_registeredSlaveModeSymbols;
+	set<MasterMode> m_registeredMasterModeSymbols;
+	set<MessageTag> m_registeredMessageTagSymbols;
+
+	map<PluginHandle,RegisteredPlugin> m_plugins;
+
+/** the maximum number of messages with a non-NULL buffers in
+ * the outbox */
+	int m_maximumAllocatedOutboxBuffers;
+	int m_maximumAllocatedInboxBuffers;
+
+
+/** the maximum number of messages in the outbox */
+	int m_maximumNumberOfOutboxMessages;
+
+/** the maximum number of inbox messages */
+	int m_maximumNumberOfInboxMessages;
+
+	/** the virtual communicator of the MPI rank */
+	VirtualCommunicator m_virtualCommunicator;
+
+	/** the virtual processor of the MPI rank */
+	VirtualProcessor m_virtualProcessor;
+
+	uint64_t m_startingTimeMicroseconds;
+
+	Rank m_rank;
+	int m_size;
+	bool m_showCommunicationEvents;
+	bool m_profilerVerbose;
+	bool m_runProfiler;
+
+/** the profiler
+ * enabled with -run-profiler
+ */
+	Profiler m_profiler;
+
+/** the switch man */
+	SwitchMan m_switchMan;
+	TickLogger m_tickLogger;
+
+/** the message router */
+	MessageRouter m_router;
+	bool m_routerIsEnabled;
+
+	StaticVector m_outbox;
+	StaticVector m_inbox;
+
+	/** middleware to handle messages */
+	MessagesHandler m_messagesHandler;
+
+/** this object handles messages */
+	MessageTagExecutor m_messageTagExecutor;
+
+/** this object handles master modes */
+	MasterModeExecutor m_masterModeExecutor;
+
+/* this object handles slave modes */
+	SlaveModeExecutor m_slaveModeExecutor;
+
+	// allocator for outgoing messages
+	RingAllocator m_outboxAllocator;
+	
+	// allocator for ingoing messages
+	RingAllocator m_inboxAllocator;
+
+	SlaveMode m_currentSlaveModeToAllocate;
+	MasterMode m_currentMasterModeToAllocate;
+	MessageTag m_currentMessageTagToAllocate;
+
+/** is the program alive ? */
+	bool m_alive;
+
+	void runVanilla();
+	void runWithProfiler();
+
+	void receiveMessages();
+	void sendMessages();
+	void processData();
+	void processMessages();
+
+	PluginHandle generatePluginHandle();
+
+	bool validationPluginAllocated(PluginHandle plugin);
+	bool validationSlaveModeOwnership(PluginHandle plugin,SlaveMode handle);
+	bool validationMasterModeOwnership(PluginHandle plugin,MasterMode handle);
+	bool validationMessageTagOwnership(PluginHandle plugin,MessageTag handle);
+
+	bool validationMessageTagSymbolAvailable(PluginHandle plugin,const char*symbol);
+	bool validationSlaveModeSymbolAvailable(PluginHandle plugin,const char*symbol);
+	bool validationMasterModeSymbolAvailable(PluginHandle plugin,const char*symbol);
+	bool validationMessageTagSymbolRegistered(PluginHandle plugin,const char*symbol);
+	bool validationSlaveModeSymbolRegistered(PluginHandle plugin,const char*symbol);
+	bool validationMasterModeSymbolRegistered(PluginHandle plugin,const char*symbol);
+
+	bool validationMessageTagSymbolNotRegistered(PluginHandle plugin,MessageTag handle);
+	bool validationSlaveModeSymbolNotRegistered(PluginHandle plugin,SlaveMode handle);
+	bool validationMasterModeSymbolNotRegistered(PluginHandle plugin,MasterMode handle);
+
+	bool validationMasterModeRange(PluginHandle plugin,MasterMode i);
+	bool validationSlaveModeRange(PluginHandle p, SlaveMode i);
+	bool validationMessageTagRange(PluginHandle p,MessageTag i);
+
+	bool validationObjectSymbolNotRegistered(PluginHandle plugin,const char*symbol);
+	bool validationObjectSymbolRegistered(PluginHandle plugin,const char*symbol);
+
+	void setFatalError();
+
+	bool m_doChecksum;
+
+	void verifyMessageChecksums();
+	void addMessageChecksums();
+public:
+	/** this is the main method */
+	void run();
+
+	/** get the middleware object */
+	MessagesHandler*getMessagesHandler();
+
+	void constructor(int*argc,char***argv);
+
+	void enableProfiler();
+	void showCommunicationEvents();
+	void enableProfilerVerbosity();
+
+	Profiler*getProfiler();
+
+	TickLogger*getTickLogger();
+	SwitchMan*getSwitchMan();
+	StaticVector*getOutbox();
+	StaticVector*getInbox();
+	MessageRouter*getRouter();
+
+	void sendEmptyMessageToAll(MessageTag tag);
+
+	RingAllocator*getOutboxAllocator();
+	RingAllocator*getInboxAllocator();
+
+	bool*getLife();
+
+	void stop();
+
+	VirtualProcessor*getVirtualProcessor();
+	VirtualCommunicator*getVirtualCommunicator();
+
+	void setMaximumNumberOfOutboxBuffers(int maxNumberOfBuffers);
+	
+	void registerPlugin(CorePlugin*plugin);
+	void resolveSymbols();
+
+	void destructor();
+
+	void printPlugins(string directory);
+
+/********************************************************************/
+/** the methods below are available for plugin registration **/
+
+/** allocate an handle for a plugin **/
+	PluginHandle allocatePluginHandle();
+
+/** sets the name of a plugin **/
+	void setPluginName(PluginHandle plugin,const char*name);
+
+/** sets the description of a plugin **/
+	void setPluginDescription(PluginHandle handle,const char*text);
+
+/** sets the authors of a plugin **/
+	void setPluginAuthors(PluginHandle handle,const char*text);
+
+/** sets the license of a plugin **/
+	void setPluginLicense(PluginHandle handle,const char*text);
+
+
+
+/** allocate a master mode **/
+	MasterMode allocateMasterModeHandle(PluginHandle plugin);
+
+/** sets the symbol for a master mode **/
+	void setMasterModeSymbol(PluginHandle plugin,MasterMode mode,const char*symbol);
+
+/** get a master mode from its symbol **/
+	MasterMode getMasterModeFromSymbol(PluginHandle plugin,const char*symbol);
+
+/** add a master mode handler */
+	void setMasterModeObjectHandler(PluginHandle plugin,MasterMode mode,MasterModeHandler object);
+
+/** sets the master mode switch for a master mode
+ * this tells the core which message tag is to be automaticalled broadcasted for 
+ * a given master mode **/
+	void setMasterModeToMessageTagSwitch(PluginHandle plugin,MasterMode mode,MessageTag tag);
+
+/* The Ray engine will run these master modes in series 
+in a parallel and distributed way.
+This is for modes that support the feature.
+Not all master modes have yet been ported to that list.
+
+-Sébastien Boisvert, 2011-01-08
+*/
+	void setMasterModeNextMasterMode(PluginHandle plugin,MasterMode mode,MasterMode next);
+
+/** defines the entry point of the application **/
+	void setFirstMasterMode(PluginHandle plugin,MasterMode mode);
+
+
+
+/** allocate a slave mode for a handle **/
+	SlaveMode allocateSlaveModeHandle(PluginHandle plugin);
+
+/** sets the symbol for a slave mode **/
+	void setSlaveModeSymbol(PluginHandle plugin,SlaveMode mode,const char*symbol);
+
+/** add a slave mode handler */
+	void setSlaveModeObjectHandler(PluginHandle plugin,SlaveMode mode,SlaveModeHandler object);
+
+/** get a slave mode from its symbol **/
+	SlaveMode getSlaveModeFromSymbol(PluginHandle plugin,const char*symbol);
+
+
+
+/** allocate a handle for a message tag **/
+	MessageTag allocateMessageTagHandle(PluginHandle plugin);
+	
+/** set the symbol for a message tag **/
+	void setMessageTagSymbol(PluginHandle plugin,MessageTag mode,const char*symbol);
+
+/** get a message tag from its symbol **/
+	MessageTag getMessageTagFromSymbol(PluginHandle plugin,const char*symbol);
+
+/** add a message tag handler */
+	void setMessageTagObjectHandler(PluginHandle plugin,MessageTag tag,MessageTagHandler object);
+
+/** sets the slave switch for a slave mode
+ * this tells the core which slave mode to switch to when receiving a particular message tag **/
+	void setMessageTagToSlaveModeSwitch(PluginHandle plugin,MessageTag tag,SlaveMode mode);
+
+/** sets the reply tag for a message tag **/
+	void setMessageTagReplyMessageTag(PluginHandle plugin,MessageTag tag,MessageTag reply);
+
+/** sets the number of elements for a message tag **/
+	void setMessageTagSize(PluginHandle plugin,MessageTag tag,int size);
+
+	string getRayPlatformVersion();
+
+
+/** set object that can be shared between plugins **/
+	void setObjectSymbol(PluginHandle plugin,void*object,const char* symbol);
+
+/** get shared object from its symbol **/
+	void* getObjectFromSymbol(PluginHandle plugin,const char*symbol);
+
+	ComputeCore();
+
+	int getNumberOfArguments();
+	char**getArgumentValues();
+};
+
+#endif
+
diff --git a/RayPlatform/core/OperatingSystem.cpp b/RayPlatform/core/OperatingSystem.cpp
new file mode 100644
index 0000000..2fe05ba
--- /dev/null
+++ b/RayPlatform/core/OperatingSystem.cpp
@@ -0,0 +1,312 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <core/OperatingSystem.h>
+#include <iostream>
+#include <string>
+#include <fstream>
+#include <assert.h>
+using namespace std;
+
+/*
+ * Detect the operating system
+ */
+
+/* GNU/Linux */
+#if defined(__linux__)
+#define OS_POSIX
+
+/* the GNU stack provides all we need */
+#elif defined(__GNUC__)
+#define OS_POSIX
+
+/* assume Mac OS X and not old Mac OS */
+#elif defined(__APPLE__) || defined(MACOSX)
+#define OS_POSIX
+
+/* assume Solaris or Linux or another POSIX system on Sun or Sun Sparc */
+#elif defined(__sparc__) || defined(__sun__)
+#define OS_POSIX
+
+/* random UNIX system */
+#elif defined(__unix__)
+#define OS_POSIX
+
+/* Windows 32 bits */
+#elif defined(_WIN32) || defined(WIN32)
+#define OS_WIN
+
+/* Windoes 64 bits */
+#elif defined(_WIN64) || defined(WIN64)
+#define OS_WIN
+
+/* Cygwin in Windows */
+#elif defined(__CYGWIN__)
+#define OS_POSIX
+
+/* MinGW is not tested but probably works */
+#elif defined(__MINGW32__)
+#define OS_WIN
+
+/* this will never be picked up because WIN32 or WIN64 will be picked up */
+#elif defined(__BORLANDC__) 
+#define OS_WIN
+
+/* SGI IRIX I guess */
+#elif defined(__sgi)
+#define OS_POSIX
+
+/* what is your operating system ? */
+/* assume it is a POSIX one */
+#else
+#warning "What is your operating system ?"
+#warning "Assuming it is a POSIX system..."
+#define OS_POSIX
+
+#endif
+
+/* include some files */
+
+#ifdef OS_POSIX
+
+#include <unistd.h> /* getpid */
+#include <time.h> /* possibly clock_gettime  */
+#include <sys/time.h>  /* gettimeofday*/ 
+#include <sys/stat.h>	/* mkdir */
+#include <sys/types.h> /* mode_t */
+
+#elif defined OS_WIN
+
+#include <windows.h> /* GetCurrentProcessId */
+			/* CreateDirectory */
+#endif
+
+/** print the date, not necessary */
+void showDate(){
+	#ifdef OS_POSIX
+	time_t m_endingTime=time(NULL);
+	struct tm * timeinfo;
+	timeinfo=localtime(&m_endingTime);
+	cout<<"Date: "<<asctime(timeinfo);
+	#endif
+}
+
+int portableProcessId(){
+	#ifdef OS_POSIX
+	return getpid();
+	#elif defined(OS_WIN)
+	return GetCurrentProcessId();
+	#else
+	return -1;
+	#endif
+}
+
+/** get the operating system */
+string getOperatingSystem(){
+	#ifdef OS_WIN
+	return "Microsoft Windows (OS_WIN)";
+	#else
+		#ifdef __linux__
+		return "Linux (__linux__) POSIX (OS_POSIX)";
+		#else
+		return "POSIX (OS_POSIX)";
+		#endif
+	#endif
+	return "Unknown";
+}
+
+/** only ported to Linux */
+uint64_t getMemoryUsageInKiBytes(){
+	uint64_t count=0;
+
+	#ifdef __linux__
+	ifstream f("/proc/self/status");
+	while(!f.eof()){
+		string key;
+		f>>key;
+		if(key=="VmData:"){
+			f>>count;
+			break;
+		}
+	}
+	f.close();
+	#endif
+
+	return count;
+}
+
+/** real-time only ported to real-time POSIX systems */
+uint64_t getMilliSeconds(){
+	return getMicroseconds()/1000;
+}
+
+/** only ported to POSIX system */
+uint64_t getMicroseconds(){
+	#ifdef OS_POSIX
+
+	struct timeval theTime;
+	gettimeofday(&theTime,NULL);
+	uint64_t seconds=theTime.tv_sec;
+	uint64_t microSeconds=theTime.tv_usec;
+
+	return seconds*1000*1000+microSeconds;
+
+	#elif defined (OS_WIN)
+	
+	/* TODO: get microseconds is not implemented on Windows */
+	// could start with this: http://www.decompile.com/cpp/faq/windows_timer_api.htm
+
+	return 0;
+
+	#endif
+}
+
+uint64_t getThreadMicroseconds(){
+	#ifdef OS_POSIX
+
+	#ifdef CONFIG_CLOCK_GETTIME
+	struct timespec timeValue;
+
+	int returnValue=clock_gettime(CLOCK_THREAD_CPUTIME_ID,&timeValue);
+
+	if(returnValue != 0){
+	}
+
+	uint64_t seconds=timeValue.tv_sec;
+	uint64_t nanoSeconds=timeValue.tv_nsec;
+
+	return seconds*1000*1000 + nanoSeconds / 1000;
+
+	#else
+
+	return getMicroseconds();
+
+	#endif
+
+	#elif defined OS_WIN
+	return getMicroseconds();
+	#endif
+}
+
+/**
+ * \see http://pubs.opengroup.org/onlinepubs/009695399/functions/mkdir.html
+ * \see http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysstat.h.html
+ * \see http://www.computing.net/answers/programming/c-createdirectory/13483.html
+ *
+ * \see http://msdn.microsoft.com/en-us/library/aa363855(v=vs.85).aspx
+ */
+void createDirectory(const char*directory){
+	#ifdef OS_POSIX
+
+	/* 
+ * S_IRWXU
+    read, write, execute/search by owner 
+ *
+ * S_IRWXG
+ *  read, write, execute/search by group 
+ *     */
+	mode_t mode=S_IRWXU | S_IRWXG;
+
+	#ifdef ASSERT
+	int status=
+	#endif
+
+	mkdir(directory,mode);
+
+	#ifdef ASSERT
+	if(status!=0){
+		cout<<"mkdir returned status "<<status<<" with directory= "<<directory<<endl;
+	}
+
+	assert(status==0);
+	#endif
+	
+	#elif defined(OS_WIN)
+
+	LPSECURITY_ATTRIBUTES attr=NULL;
+	CreateDirectory(directory,attr);
+
+	#endif
+}
+
+/** \see http://pubs.opengroup.org/onlinepubs/009695399/functions/stat.html
+ * \see http://blog.kowalczyk.info/article/Check-if-file-exists-on-Windows.html */
+bool fileExists(const char*file){
+	#ifdef OS_POSIX
+	struct stat st;
+	int returnValue=stat(file,&st);
+	
+	bool theFileExists=(returnValue == 0);
+	return theFileExists;
+	
+	#elif defined(OS_WIN)
+	/* Return TRUE if file 'fileName' exists */
+	DWORD fileAttr = GetFileAttributes(fileName);
+	if(0xFFFFFFFF == fileAttr)
+		return false;
+    	return true;
+	
+	#else
+	/* not implemented */
+	#endif
+}
+
+void showMemoryUsage(int rank){
+	uint64_t count=getMemoryUsageInKiBytes();
+	cout<<"Rank "<<rank<<": assembler memory usage: "<<count<<" KiB"<<endl;
+	cout.flush();
+}
+
+void printTheSeconds(int difference,ostream*stream){
+	int minutes=difference/60;
+	int seconds=difference%60;
+	int hours=minutes/60;
+	minutes=minutes%60;
+	int days=hours/24;
+	hours=hours%24;
+
+	bool printed=false;
+
+	if(days>0){
+		(*stream)<<days<<" days";
+		printed=true;
+	}
+	if(hours>0){
+		if(printed){
+			(*stream)<<", ";
+		}
+		printed=true;
+		(*stream)<<hours<<" hours";
+	}
+	if(minutes>0){
+		if(printed){
+			(*stream)<<", ";
+		}
+		printed=true;
+		(*stream)<<minutes<<" minutes";
+	}
+
+	if(printed){
+		(*stream)<<", ";
+	}
+	(*stream)<<seconds<<" seconds";
+
+}
diff --git a/RayPlatform/core/OperatingSystem.h b/RayPlatform/core/OperatingSystem.h
new file mode 100644
index 0000000..715a929
--- /dev/null
+++ b/RayPlatform/core/OperatingSystem.h
@@ -0,0 +1,77 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _OperatingSystem_h
+#define _OperatingSystem_h
+
+/* EXIT_SUCCESS 0 (defined in stdlib.h) */
+#define EXIT_NEEDS_ARGUMENTS 5
+#define EXIT_NO_MORE_MEMORY 42
+
+/*
+ Open-MPI eager threshold is 4k (4096), and this include Open-MPI's metadata.
+ tests show that 4096-100 bytes are sent eagerly, too.
+ divide that by eight and you get the number of 64-bit integers 
+ allowed in a single eager communication
+
+ * "4096 is rendezvous. For eager, try 4000 or lower. "
+ *  --Eugene Loh  (Oracle)
+ *  http://www.open-mpi.org/community/lists/devel/2010/11/8700.php
+ *
+ */
+
+
+/** only this file knows the operating system */
+#include <string>
+//#include <core/constants.h> 
+#include <communication/MessagesHandler.h>
+using namespace std;
+
+/** show memory usage */
+uint64_t getMemoryUsageInKiBytes();
+
+string getOperatingSystem();
+
+void showDate();
+
+/**
+ * get the process identifier 
+ */
+int portableProcessId();
+
+uint64_t getMilliSeconds();
+
+void showMemoryUsage(int rank);
+
+uint64_t getMicroseconds();
+
+uint64_t getThreadMicroseconds();
+
+/** create a directory */
+void createDirectory(const char*directory);
+
+bool fileExists(const char*file);
+
+void printTheSeconds(int seconds,ostream*stream);
+
+
+
+#endif
diff --git a/RayPlatform/core/master_modes.cpp b/RayPlatform/core/master_modes.cpp
new file mode 100644
index 0000000..97d3409
--- /dev/null
+++ b/RayPlatform/core/master_modes.cpp
@@ -0,0 +1,25 @@
+/*
+ 	Ray
+    Copyright (C) 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <core/master_modes.h>
+
+char MASTER_MODES[MAXIMUM_NUMBER_OF_MASTER_HANDLERS][128];
+
diff --git a/code/application_core/ray_main.cpp b/RayPlatform/core/master_modes.h
similarity index 52%
copy from code/application_core/ray_main.cpp
copy to RayPlatform/core/master_modes.h
index cbe8b74..ffcda50 100644
--- a/code/application_core/ray_main.cpp
+++ b/RayPlatform/core/master_modes.h
@@ -5,28 +5,24 @@
 	http://DeNovoAssembler.SourceForge.Net/
 
     This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
+    it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, version 3 of the License.
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
+    GNU Lesser General Public License for more details.
 
-    You have received a copy of the GNU General Public License
-    along with this program (gpl-3.0.txt).  
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
 	see <http://www.gnu.org/licenses/>
-
 */
 
-#include <iostream>
-#include <application_core/Machine.h>
-#include <stdlib.h>
-using namespace std;
+#ifndef _master_modes
+#define _master_modes
+
+#include <core/types.h>
 
-int main(int argc,char**argv){
-	Machine*m=new Machine(argc,argv);
-	m->start();
-	return EXIT_SUCCESS;
-}
+extern char MASTER_MODES[MAXIMUM_NUMBER_OF_MASTER_HANDLERS][128];
 
+#endif
diff --git a/RayPlatform/core/slave_modes.cpp b/RayPlatform/core/slave_modes.cpp
new file mode 100644
index 0000000..7975b96
--- /dev/null
+++ b/RayPlatform/core/slave_modes.cpp
@@ -0,0 +1,24 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <core/slave_modes.h>
+
+char SLAVE_MODES[MAXIMUM_NUMBER_OF_SLAVE_HANDLERS][128];
diff --git a/code/application_core/ray_main.cpp b/RayPlatform/core/slave_modes.h
similarity index 52%
copy from code/application_core/ray_main.cpp
copy to RayPlatform/core/slave_modes.h
index cbe8b74..4c85d67 100644
--- a/code/application_core/ray_main.cpp
+++ b/RayPlatform/core/slave_modes.h
@@ -5,28 +5,24 @@
 	http://DeNovoAssembler.SourceForge.Net/
 
     This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
+    it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, version 3 of the License.
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
+    GNU Lesser General Public License for more details.
 
-    You have received a copy of the GNU General Public License
-    along with this program (gpl-3.0.txt).  
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
 	see <http://www.gnu.org/licenses/>
-
 */
 
-#include <iostream>
-#include <application_core/Machine.h>
-#include <stdlib.h>
-using namespace std;
+#ifndef _slave_modes
+#define _slave_modes
+
+#include <core/types.h>
 
-int main(int argc,char**argv){
-	Machine*m=new Machine(argc,argv);
-	m->start();
-	return EXIT_SUCCESS;
-}
+extern char SLAVE_MODES[MAXIMUM_NUMBER_OF_SLAVE_HANDLERS][128];
 
+#endif
diff --git a/RayPlatform/core/statistics.cpp b/RayPlatform/core/statistics.cpp
new file mode 100644
index 0000000..c5d5436
--- /dev/null
+++ b/RayPlatform/core/statistics.cpp
@@ -0,0 +1,118 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#include <core/statistics.h>
+#include <math.h> /* for sqrt */
+#include <stdint.h>
+#include <map>
+using namespace std;
+
+double getAverage(vector<int>*values){
+	int i=0;
+	int n=values->size();
+	int sum=0;
+	while(i<n){
+		sum+=values->at(i);
+		i++;
+	}
+
+	double average=sum;
+
+	if(n > 0){
+		average /= n;
+	}
+
+	return average;
+}
+
+/** compute the standard deviation */
+double getStandardDeviation(vector<int>*x){
+	int i=0;
+
+	double averageValue=getAverage(x);
+	uint64_t sum=0;
+
+	int n=x->size();
+
+	while(i<n){
+		int diff=(int)(x->at(i)-averageValue);
+		sum+=diff*diff;
+		i++;
+	}
+
+	double standardDeviation=sqrt(sum+0.0);
+	
+	if(n > 0){
+		standardDeviation=sqrt((sum+0.0)/n);
+	}
+
+	return standardDeviation;
+}
+
+int getMode(vector<int>*x){
+	map<int,int> data;
+	for(int i=0;i<(int)x->size();i++){
+		data[x->at(i)]++;
+	}
+	int best=-1;
+
+	for(map<int,int>::iterator i=data.begin();
+		i!=data.end();i++){
+		if(data.count(best)==0 || i->second > data[best]){
+			best=i->first;
+		}
+	}
+
+	return best;
+}
+
+int getAverageFromFrequencies(vector<int>*data,vector<int>*frequencies){
+	uint64_t sum=0;
+	int count=0;
+	for(int i=0;i<(int)data->size();i++){
+		sum+=data->at(i)*frequencies->at(i);
+		count+=frequencies->at(i);
+	}
+
+	uint64_t average=sum;
+	if(count>0)
+		average/=count;
+
+	return average;
+}
+
+int getDeviationFromFrequencies(vector<int>*data,vector<int>*frequencies){
+	int average=getAverageFromFrequencies(data,frequencies);
+
+	uint64_t sum=0;
+	int count=0;
+	for(int i=0;i<(int)data->size();i++){
+		int difference=average-data->at(i);
+		sum+=(difference*difference)*frequencies->at(i);
+		count+=frequencies->at(i);
+	}
+
+	uint64_t deviation=sum;
+
+	if(count>0)
+		deviation/=count;
+
+	return (int)sqrt(0.0+deviation);
+}
diff --git a/RayPlatform/core/statistics.h b/RayPlatform/core/statistics.h
new file mode 100644
index 0000000..ab7f24d
--- /dev/null
+++ b/RayPlatform/core/statistics.h
@@ -0,0 +1,38 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _statistics_h
+#define _statistics_h
+
+#include <vector>
+using namespace std;
+
+double getAverage(vector<int>*values);
+
+/** compute the standard deviation */
+double getStandardDeviation(vector<int>*x);
+
+int getMode(vector<int>*x);
+
+
+int getDeviationFromFrequencies(vector<int>*data,vector<int>*frequencies);
+int getAverageFromFrequencies(vector<int>*data,vector<int>*frequencies);
+
+#endif
diff --git a/RayPlatform/core/types.h b/RayPlatform/core/types.h
new file mode 100644
index 0000000..c29229f
--- /dev/null
+++ b/RayPlatform/core/types.h
@@ -0,0 +1,66 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _types_h
+#define _types_h
+
+#include <stdint.h>
+
+typedef int Rank;
+
+typedef int MessageTag;
+
+typedef int SlaveMode;
+
+typedef int MasterMode;
+
+typedef int Distance;
+
+#define MAXIMUM_NUMBER_OF_MASTER_HANDLERS 64
+#define MAXIMUM_NUMBER_OF_SLAVE_HANDLERS  64
+#define MAXIMUM_NUMBER_OF_TAG_HANDLERS 256
+
+typedef uint64_t PluginHandle;
+
+#define INVALID_HANDLE -9876
+
+/* an handle for a worker */
+typedef uint64_t WorkerHandle;
+
+/*************************************************/
+/* compile-time configuration of RayPlatform */
+
+// the maximum number of tags
+#define MAXIMUM_NUMBER_OF_TAGS 256
+
+/* a basic unit for message buffers */
+typedef uint64_t MessageUnit;
+
+#define MAXIMUM_MESSAGE_SIZE_IN_BYTES 4000
+
+#define MASTER_RANK 0
+
+/* the maximum of processes is utilized to construct unique hyperfusions IDs */
+// with routing enabled, MAX_NUMBER_OF_MPI_PROCESSES is 4096
+#define MAX_NUMBER_OF_MPI_PROCESSES 1000000
+#define INVALID_RANK MAX_NUMBER_OF_MPI_PROCESSES
+
+#endif
diff --git a/RayPlatform/cryptography/crypto.cpp b/RayPlatform/cryptography/crypto.cpp
new file mode 100644
index 0000000..daf5e7f
--- /dev/null
+++ b/RayPlatform/cryptography/crypto.cpp
@@ -0,0 +1,193 @@
+/*
+ 	RayPlatform
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You have received a copy of the GNU General Public License
+    along with this program (gpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <cryptography/crypto.h>
+#include <string.h>
+
+#ifdef ASSERT
+#include <assert.h>
+#endif
+
+/*
+ * Basically, we take a 64-bit unsigned integer (the sign does not matter..)
+ * and we compute the image corresponding to a uniform distribution.
+ *
+ * see http://www.concentric.net/~Ttwang/tech/inthash.htm 64 bit Mix Functions
+ */
+uint64_t uniform_hashing_function_1_64_64(uint64_t key){
+	// some magic here and there.
+	key = (~key) + (key << 21); 
+	key = key ^ (key >> 24);
+	key = (key + (key << 3)) + (key << 8); 
+	key = key ^ (key >> 14);
+	key = (key + (key << 2)) + (key << 4); 
+	key = key ^ (key >> 28);
+	key = key + (key << 31);
+	return key;
+}
+
+/*
+ * based on uniform_hashing_function_1_64_64, but with different values
+ */
+uint64_t uniform_hashing_function_2_64_64(uint64_t key){
+	key = (~key) + (key << 31); 
+	key = key ^ (key >> 14);
+	key = (key + (key << 7)) + (key << 11); 
+	key = key ^ (key >> 13);
+	key = (key + (key << 4)) + (key << 8); 
+	key = key ^ (key >> 44);
+	key = key + (key << 6);
+	return key;
+}
+
+// enable this if you have sse4_2
+//   'grep sse4_2 /proc/cpuinfo' will tell you if you have it in Linux.
+//#define CONFIG_SSE_4_2
+
+#ifdef __SSE4_2__ /* this is set if compiled with gcc -march=native */
+#define CONFIG_SSE_4_2
+#endif /* __SSE4_2__ */
+
+#ifdef CONFIG_SSE_4_2
+
+/**
+ * this code is from the Internet.
+ * \see http://byteworm.com/2010/10/13/crc32/
+ */
+uint32_t computeCyclicRedundancyCode32(uint8_t*str, uint32_t len) {
+	uint32_t q=len/sizeof(uint32_t),
+		r=len%sizeof(uint32_t),
+		*p=(uint32_t*)str, crc;
+
+	crc=0;
+	while (q--) {
+		__asm__ __volatile__(
+			".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
+			:"=S"(crc)
+			:"0"(crc), "c"(*p)
+		);
+		p++;
+	}
+
+	str=(uint8_t*)p;
+	while (r--) {
+		__asm__ __volatile__(
+			".byte 0xf2, 0xf, 0x38, 0xf0, 0xf1"
+			:"=S"(crc)
+			:"0"(crc), "c"(*str)
+		);
+		str++;
+	}
+
+	return crc;
+}
+
+#else
+
+// This table is from http://www.arturocampos.com/ac_crc32.html
+uint32_t crc_table[256] =
+  {
+  0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419,
+  0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4,
+  0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07,
+  0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+  0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856,
+  0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
+  0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
+  0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+  0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
+  0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A,
+  0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599,
+  0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+  0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190,
+  0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
+  0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E,
+  0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+  0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
+  0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
+  0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3,
+  0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+  0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
+  0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
+  0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010,
+  0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+  0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17,
+  0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6,
+  0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
+  0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+  0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344,
+  0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
+  0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A,
+  0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+  0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1,
+  0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
+  0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
+  0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+  0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE,
+  0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
+  0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C,
+  0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+  0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B,
+  0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
+  0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1,
+  0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+  0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
+  0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
+  0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66,
+  0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+  0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
+  0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8,
+  0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
+  0x2D02EF8D
+  };
+
+/**
+ * \see http://www.arturocampos.com/ac_crc32.html
+ * \see http://arsene.perez-mas.pagesperso-orange.fr/langc/operateurs/operateurs.htm
+ */
+uint32_t computeCyclicRedundancyCode32(uint8_t*bytes,uint32_t numberOfBytes){
+
+	uint32_t checksum=0xffffffff;
+
+	for(uint32_t i=0;i<numberOfBytes;i++){
+		uint8_t byte=bytes[i];
+
+		uint8_t position=(byte ^ checksum) & 0xff;
+
+		#ifdef ASSERT
+		assert(position>=0);
+		assert(position<256);
+		#endif
+
+		uint32_t tableValue=crc_table[position];
+
+		checksum >>= 8;
+
+		checksum ^= tableValue;
+	}
+
+	checksum ^= 0xffffffff;
+
+	return checksum;
+
+}
+
+#endif
diff --git a/code/plugin_PhylogenyViewer/types.h b/RayPlatform/cryptography/crypto.h
similarity index 67%
copy from code/plugin_PhylogenyViewer/types.h
copy to RayPlatform/cryptography/crypto.h
index a95753d..1a7b33b 100644
--- a/code/plugin_PhylogenyViewer/types.h
+++ b/RayPlatform/cryptography/crypto.h
@@ -1,6 +1,6 @@
 /*
- 	Ray
-    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+ 	RayPlatform
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
 
 	http://DeNovoAssembler.SourceForge.Net/
 
@@ -16,16 +16,17 @@
     You have received a copy of the GNU General Public License
     along with this program (gpl-3.0.txt).  
 	see <http://www.gnu.org/licenses/>
+
 */
 
-#ifndef _PhylogenyTypes_h
-#define _PhylogenyTypes_h
+#ifndef _crypto
+#define _crypto
 
-#include <stdint.h>
+#include<stdint.h>
 
-typedef uint64_t TaxonIdentifier;
+uint64_t uniform_hashing_function_1_64_64(uint64_t key);
+uint64_t uniform_hashing_function_2_64_64(uint64_t key);
 
-typedef uint64_t GenomeIdentifier;
+uint32_t computeCyclicRedundancyCode32(uint8_t*bytes,uint32_t numberOfBytes);
 
 #endif
-
diff --git a/RayPlatform/git.txt b/RayPlatform/git.txt
new file mode 100644
index 0000000..e48ae69
--- /dev/null
+++ b/RayPlatform/git.txt
@@ -0,0 +1 @@
+git://github.com/sebhtml/RayPlatform.git
diff --git a/RayPlatform/github.txt b/RayPlatform/github.txt
new file mode 100644
index 0000000..292990c
--- /dev/null
+++ b/RayPlatform/github.txt
@@ -0,0 +1 @@
+https://github.com/sebhtml/RayPlatform
diff --git a/RayPlatform/handlers/MasterModeExecutor.cpp b/RayPlatform/handlers/MasterModeExecutor.cpp
new file mode 100644
index 0000000..d0ec30a
--- /dev/null
+++ b/RayPlatform/handlers/MasterModeExecutor.cpp
@@ -0,0 +1,59 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+
+
+#include <handlers/MasterModeExecutor.h>
+#include <core/types.h>
+#include <stdlib.h> /* for NULL */
+
+#ifdef ASSERT
+#include <assert.h>
+#endif
+
+void MasterModeExecutor::callHandler(MasterMode mode){
+	MasterModeHandler object=m_objects[mode];
+
+	// don't do it if it is NULL because it does nothing
+	if(object==NULL)
+		return;
+
+	/** otherwise, fetch the method and call it*/
+
+	object();
+}
+
+MasterModeExecutor::MasterModeExecutor(){
+	for(int i=0;i<MAXIMUM_NUMBER_OF_MASTER_HANDLERS;i++){
+		m_objects[i]=NULL;
+	}
+}
+
+void MasterModeExecutor::setObjectHandler(MasterMode mode,MasterModeHandler object){
+
+	#ifdef ASSERT
+	assert(mode>=0);
+	assert(mode < MAXIMUM_NUMBER_OF_MASTER_HANDLERS);
+	#endif
+
+	m_objects[mode]=object;
+}
+
+
diff --git a/RayPlatform/handlers/MasterModeExecutor.h b/RayPlatform/handlers/MasterModeExecutor.h
new file mode 100644
index 0000000..67d0fab
--- /dev/null
+++ b/RayPlatform/handlers/MasterModeExecutor.h
@@ -0,0 +1,46 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _MasterModeExecutor_h
+#define _MasterModeExecutor_h
+
+#include <core/types.h>
+#include <core/master_modes.h>
+#include <handlers/MasterModeHandler.h>
+
+class MasterModeExecutor{
+
+/** a list of objects to use for calling methods */
+	MasterModeHandler m_objects[MAXIMUM_NUMBER_OF_MASTER_HANDLERS];
+
+public:
+	/** call the handler */
+	void callHandler(MasterMode mode);
+
+/** set the correct object to call for a given master mode */
+	void setObjectHandler(MasterMode mode, MasterModeHandler object);
+
+/** initialise default object and method handlers */
+	MasterModeExecutor();
+
+};
+
+#endif
+
diff --git a/RayPlatform/handlers/MasterModeHandler.h b/RayPlatform/handlers/MasterModeHandler.h
new file mode 100644
index 0000000..41e102e
--- /dev/null
+++ b/RayPlatform/handlers/MasterModeHandler.h
@@ -0,0 +1,42 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _MasterModeHandler_h
+#define _MasterModeHandler_h
+
+/* this is a macro to create the cpp code for an adapter */
+#define __CreateMasterModeAdapter( corePlugin,handle )\
+void __GetAdapter( corePlugin, handle ) () { \
+	__GetPlugin( corePlugin ) -> __GetMethod( handle ) () ; \
+} 
+
+
+#include <core/types.h>
+#include <core/master_modes.h>
+
+/**
+ * base class for handling master modes 
+ * \author Sébastien Boisvert
+ * with help from Élénie Godzaridis for the design
+ * \date 2012-08-08 replaced this with function pointers
+ */
+typedef void (*MasterModeHandler) () /* */ ;
+
+#endif
diff --git a/RayPlatform/handlers/MessageTagExecutor.cpp b/RayPlatform/handlers/MessageTagExecutor.cpp
new file mode 100644
index 0000000..927cfd5
--- /dev/null
+++ b/RayPlatform/handlers/MessageTagExecutor.cpp
@@ -0,0 +1,56 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#include <handlers/MessageTagHandler.h>
+#include <handlers/MessageTagExecutor.h>
+#include <communication/mpi_tags.h>
+#ifdef ASSERT
+#include <assert.h>
+#endif
+#include <stdlib.h> /* for NULL */
+
+
+void MessageTagExecutor::callHandler(MessageTag messageTag,Message*message){
+	MessageTagHandler object=m_objects[messageTag];
+
+	// it is useless to call base implementations
+	// because they are empty
+	if(object==NULL)
+		return;
+
+	object(message);
+}
+
+MessageTagExecutor::MessageTagExecutor(){
+	for(int i=0;i<MAXIMUM_NUMBER_OF_TAG_HANDLERS;i++){
+		m_objects[i]=NULL;
+	}
+}
+
+void MessageTagExecutor::setObjectHandler(MessageTag messageTag,MessageTagHandler object){
+
+	#ifdef ASSERT
+	assert(messageTag>=0);
+	assert(messageTag < MAXIMUM_NUMBER_OF_TAG_HANDLERS);
+	#endif
+
+	m_objects[messageTag]=object;
+}
+
diff --git a/RayPlatform/handlers/MessageTagExecutor.h b/RayPlatform/handlers/MessageTagExecutor.h
new file mode 100644
index 0000000..b226424
--- /dev/null
+++ b/RayPlatform/handlers/MessageTagExecutor.h
@@ -0,0 +1,52 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+
+
+#ifndef _MessageTagExecutor_h
+#define _MessageTagExecutor_h
+
+#include <handlers/MessageTagHandler.h>
+#include <communication/Message.h>
+#include <core/types.h>
+#include <communication/mpi_tags.h>
+
+
+class MessageTagExecutor{
+
+
+/** table of object handlers */
+	MessageTagHandler m_objects[MAXIMUM_NUMBER_OF_TAG_HANDLERS];
+
+public:
+
+	/** call the correct handler for a tag on a message */
+	void callHandler(MessageTag messageTag,Message*message);
+
+/** set the object to call for a given tag */
+	void setObjectHandler(MessageTag messageTag,MessageTagHandler object);
+
+/** set default object and method handlers */
+	MessageTagExecutor();
+
+
+};
+
+#endif
diff --git a/RayPlatform/handlers/MessageTagHandler.h b/RayPlatform/handlers/MessageTagHandler.h
new file mode 100644
index 0000000..51f426c
--- /dev/null
+++ b/RayPlatform/handlers/MessageTagHandler.h
@@ -0,0 +1,46 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _MessageTagHandler_h
+#define _MessageTagHandler_h
+
+
+/* this is a macro to create the cpp code for an adapter */
+#define __CreateMessageTagAdapter( corePlugin, handle ) \
+void __GetAdapter( corePlugin, handle) ( Message*message ) { \
+	__GetPlugin( corePlugin ) -> __GetMethod( handle ) ( message ) ; \
+} 
+
+
+
+#include <communication/Message.h>
+#include <core/types.h>
+#include <communication/mpi_tags.h>
+
+/**
+ * base class for handling message tags
+ * \author Sébastien Boisvert
+ * with help from Élénie Godzaridis for the design
+ * \date 2012-08-08 replaced this with function pointers
+ */
+typedef void (*MessageTagHandler) (Message*message) /* */ ;
+
+
+#endif
diff --git a/RayPlatform/handlers/SlaveModeExecutor.cpp b/RayPlatform/handlers/SlaveModeExecutor.cpp
new file mode 100644
index 0000000..d291398
--- /dev/null
+++ b/RayPlatform/handlers/SlaveModeExecutor.cpp
@@ -0,0 +1,56 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#include <handlers/SlaveModeExecutor.h>
+
+#ifdef ASSERT
+#include <assert.h>
+#endif
+#include <stdlib.h> /* for NULL */
+
+void SlaveModeExecutor::callHandler(SlaveMode mode){
+	SlaveModeHandler object=m_objects[mode];
+
+	// don't call it if it is NULL
+	if(object==NULL)
+		return;
+
+	// call it
+	object();
+}
+
+SlaveModeExecutor::SlaveModeExecutor(){
+	for(int i=0;i<MAXIMUM_NUMBER_OF_SLAVE_HANDLERS;i++){
+		m_objects[i]=NULL;
+	}
+}
+
+void SlaveModeExecutor::setObjectHandler(SlaveMode mode,SlaveModeHandler object){
+
+	#ifdef ASSERT
+	assert(mode>=0);
+	assert(mode<MAXIMUM_NUMBER_OF_SLAVE_HANDLERS);
+	#endif
+
+	m_objects[mode]=object;
+}
+
+
+
diff --git a/RayPlatform/handlers/SlaveModeExecutor.h b/RayPlatform/handlers/SlaveModeExecutor.h
new file mode 100644
index 0000000..242f10a
--- /dev/null
+++ b/RayPlatform/handlers/SlaveModeExecutor.h
@@ -0,0 +1,50 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+
+
+
+#ifndef _SlaveModeExecutor_h
+#define _SlaveModeExecutor_h
+
+#include <handlers/SlaveModeHandler.h>
+#include <core/slave_modes.h>
+#include <core/types.h>
+
+class SlaveModeExecutor{
+
+/** table of slave objects */
+	SlaveModeHandler m_objects[MAXIMUM_NUMBER_OF_SLAVE_HANDLERS];
+
+public:
+
+/** call the handler for a given slave mode */
+	void callHandler(SlaveMode mode);
+
+/** initialise default object and method handlers */
+	SlaveModeExecutor();
+
+/** set the object to call for a slave mode */
+	void setObjectHandler(SlaveMode mode,SlaveModeHandler object);
+
+};
+
+#endif
+
diff --git a/RayPlatform/handlers/SlaveModeHandler.h b/RayPlatform/handlers/SlaveModeHandler.h
new file mode 100644
index 0000000..6146d29
--- /dev/null
+++ b/RayPlatform/handlers/SlaveModeHandler.h
@@ -0,0 +1,42 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _SlaveModeHandler_h
+#define _SlaveModeHandler_h
+
+#include <core/slave_modes.h>
+#include <core/types.h>
+
+/* this is a macro to create the cpp code for an adapter */
+#define __CreateSlaveModeAdapter( corePlugin,handle ) \
+void __GetAdapter( corePlugin, handle ) () { \
+	__GetPlugin( corePlugin ) -> __GetMethod( handle ) () ; \
+} 
+
+/**
+ * base class for handling slave modes 
+ * \author Sébastien Boisvert
+ * with help from Élénie Godzaridis for the design
+ * \date 2012-08-08 replaced this with function pointers
+ */
+typedef void (*SlaveModeHandler) () /* */ ;
+
+
+#endif
diff --git a/RayPlatform/lgpl-3.0.txt b/RayPlatform/lgpl-3.0.txt
new file mode 100644
index 0000000..65c5ca8
--- /dev/null
+++ b/RayPlatform/lgpl-3.0.txt
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/RayPlatform/memory/ChunkAllocatorWithDefragmentation.cpp b/RayPlatform/memory/ChunkAllocatorWithDefragmentation.cpp
new file mode 100644
index 0000000..2fde554
--- /dev/null
+++ b/RayPlatform/memory/ChunkAllocatorWithDefragmentation.cpp
@@ -0,0 +1,221 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#include <memory/ChunkAllocatorWithDefragmentation.h>
+#include <memory/allocator.h>
+
+#ifdef ASSERT
+#include <assert.h>
+#endif
+
+#include <iostream>
+using namespace std;
+
+/** this does nothing
+ * defragmentation instead occurs sometimes when
+ * deallocate() is called
+ */
+void ChunkAllocatorWithDefragmentation::defragment(){
+}
+
+/**
+* print allocator information
+*/
+void ChunkAllocatorWithDefragmentation::print(){
+	cout<<"DefragmentationLane objects: "<<m_numberOfLanes<<endl;
+
+	for(int i=0;i<m_numberOfLanes;i++){
+		DefragmentationLane*lane=m_defragmentationLanes[i];
+		#ifdef ASSERT
+		assert(lane!=NULL);
+		#endif
+		cout<<"DefragmentationGroup objects in DefragmentationLane # "<<lane->getNumber()<<endl;
+		for(int group=0;group<GROUPS_PER_LANE;group++){
+
+			DefragmentationGroup*theGroup=lane->getGroup(group);
+			if(theGroup->isOnline()){
+				int availableElements=theGroup->getAvailableElements();
+
+				cout<<" # "<<group<<" usage: "<<(ELEMENTS_PER_GROUP-availableElements)<<"/"<<ELEMENTS_PER_GROUP;
+				cout<<" FreeSliceStart="<<theGroup->getFreeSliceStart();
+
+				cout<<" Fragmented="<<theGroup->getFragmentedElements();
+				cout<<" Contiguous="<<theGroup->getContiguousElements();
+
+				cout<<endl;
+				cout<<"   operations: ";
+				cout<<" "<<theGroup->getOperations(__OPERATION_ALLOCATE)<<" allocate calls;";
+ 				cout<<" "<<theGroup->getOperations(__OPERATION_DEALLOCATE)<<" deallocate calls;";
+				cout<<" "<<theGroup->getOperations(__OPERATION_DEFRAGMENT)<<" defragment calls"<<endl;
+
+			}
+		}
+	}
+}
+
+/** clear allocations */
+void ChunkAllocatorWithDefragmentation::destructor(){
+	/** destroy DefragmentationLanes */
+	for(int i=0;i<m_numberOfLanes;i++){
+		DefragmentationLane*lane=m_defragmentationLanes[i];
+		for(int group=0;group<GROUPS_PER_LANE;group++){
+			if(lane->getGroup(group)->isOnline())
+				lane->getGroup(group)->destructor(m_show);
+		}
+		__Free(lane,"RAY_MALLOC_TYPE_DEFRAG_LANE",m_show);
+		m_defragmentationLanes[i]=NULL;
+	}
+	__Free(m_cellOccupancies,"RAY_MALLOC_TYPE_DEFRAG_LANE",m_show);
+	__Free(m_cellContents,"RAY_MALLOC_TYPE_DEFRAG_LANE",m_show);
+	m_cellContents=NULL;
+	m_cellOccupancies=NULL;
+}
+
+/** constructor almost does nothing  */
+void ChunkAllocatorWithDefragmentation::constructor(int bytesPerElement,bool show){
+	m_cellContents=(uint16_t*)__Malloc(ELEMENTS_PER_GROUP*sizeof(uint16_t),"RAY_MALLOC_TYPE_DEFRAG_LANE",show);
+	m_cellOccupancies=(uint8_t*)__Malloc(ELEMENTS_PER_GROUP*sizeof(uint8_t),"RAY_MALLOC_TYPE_DEFRAG_LANE",show);
+	m_show=show;
+	m_bytesPerElement=bytesPerElement;
+
+	// initially, the allocator has
+	// no line
+	for(int i=0;i<NUMBER_OF_LANES;i++)
+		m_defragmentationLanes[i]=NULL;
+
+	// furthermore, the fast lane
+	// Is not set
+	m_fastLane=NULL;
+	m_numberOfLanes=0;
+}
+
+/**
+ * This method updates the fast lane
+ * update:
+ *  m_fastLane
+ *  m_fastGroup
+ *  m_fastLaneNumber
+ */
+void ChunkAllocatorWithDefragmentation::updateFastLane(int n){
+	/** find a DefragmentationGroup in a DefragmentationLane that 
+ * can accomodate the query */
+	for(int i=0;i<m_numberOfLanes;i++){
+		DefragmentationLane*lane=m_defragmentationLanes[i];
+		if(lane->canAllocate(n,m_bytesPerElement,m_show)){
+			m_fastLane=lane;
+			return;
+		}
+	}
+
+	/** we need to add a defragmentation lane because the existing lanes have
+ * 	no group that can allocate the query */
+	
+	DefragmentationLane*defragmentationLane=(DefragmentationLane*)__Malloc(sizeof(DefragmentationLane),"RAY_MALLOC_TYPE_DEFRAG_LANE",m_show);
+	defragmentationLane->constructor(m_numberOfLanes,m_bytesPerElement,m_show);
+
+	m_defragmentationLanes[m_numberOfLanes++]=defragmentationLane;
+
+	/** ask the lane if it can allocate */
+	if(defragmentationLane->canAllocate(n,m_bytesPerElement,m_show))
+		m_fastLane=defragmentationLane;
+}
+
+/**
+ * allocate memory
+ */
+SmartPointer ChunkAllocatorWithDefragmentation::allocate(int n){ /** 64 is the number of buckets in a MyHashTableGroup */
+
+	// presently, this code only allocate things between 1 and 64 * sizeof(something)
+	#ifdef ASSERT
+	if(!(n>=1 && n<=64))
+		cout<<"n= "<<n<<endl;
+	assert(n>=1&&n<=64);
+	#endif
+
+	// we need to update the fast lane
+	if(m_fastLane==NULL || !m_fastLane->canAllocate(n,m_bytesPerElement,m_show)){
+		updateFastLane(n);
+	}
+
+	// the fast lane gives us a smart pointer
+	// a small smart pointer can only be resolved with the context of
+	// a DefragmentationGroup
+	int group;
+	SmallSmartPointer smallSmartPointer=m_fastLane->allocate(n,m_bytesPerElement,&group,
+		m_cellContents,m_cellOccupancies );
+
+	/** build the SmartPointer with the
+ *	SmallSmartPointer, DefragmentationLane id, and DefragmentationGroup id 
+* SmartPointer are unique contrary to SmallSmartPointer which are not
+*/
+	int globalGroup=m_fastLane->getNumber()*GROUPS_PER_LANE+group;
+	SmartPointer smartPointer=globalGroup*ELEMENTS_PER_GROUP+smallSmartPointer;
+
+	return smartPointer;
+}
+
+/**
+ * deallocate liberates the space.
+ * the bitmap is updated and m_allocatedSizes is set to 0 for a.
+ * Finally, a call to defragment is performed.
+ */
+void ChunkAllocatorWithDefragmentation::deallocate(SmartPointer a){
+	/** NULL is easy to free 
+ * 	Not sure if the code should vomit an error instead.. */
+	if(a==SmartPointer_NULL)
+		return;
+
+	/** get the DefragmentationGroup */
+	int group=a/ELEMENTS_PER_GROUP;
+	int correctLaneId=group/GROUPS_PER_LANE;
+	int groupInLane=group%GROUPS_PER_LANE;
+
+	/** forward the SmallSmartPointer to the DefragmentationGroup */
+	// this may trigger some defragmentation
+	SmallSmartPointer smallSmartPointer=a%ELEMENTS_PER_GROUP;
+	m_defragmentationLanes[correctLaneId]->getGroup(groupInLane)->deallocate(smallSmartPointer,m_bytesPerElement,m_cellContents,m_cellOccupancies);
+}
+
+/** this one is easy,
+ * Just forward the SmallSmartPointer to the DefragmentationGroup...
+ */
+void*ChunkAllocatorWithDefragmentation::getPointer(SmartPointer a){
+	if(a==SmartPointer_NULL)
+		return NULL;
+
+	// to get the virtual address from a SmartPointer,
+	// we need to find in which DefragmentationGroup it is
+	// and then we just ask this DefragmentationGroup
+	// for what we want
+	int group=a/ELEMENTS_PER_GROUP;
+	int correctLaneId=group/GROUPS_PER_LANE;
+	int groupInLane=group%GROUPS_PER_LANE;
+
+	/** the DefragmentationGroup knows how to do that */
+	SmallSmartPointer smallSmartPointer=a%ELEMENTS_PER_GROUP;
+	return m_defragmentationLanes[correctLaneId]->getGroup(groupInLane)->getPointer(smallSmartPointer,m_bytesPerElement);
+}
+
+// empty constructor
+ChunkAllocatorWithDefragmentation::ChunkAllocatorWithDefragmentation(){}
+
+// empty desctructor
+ChunkAllocatorWithDefragmentation::~ChunkAllocatorWithDefragmentation(){}
+
diff --git a/RayPlatform/memory/ChunkAllocatorWithDefragmentation.h b/RayPlatform/memory/ChunkAllocatorWithDefragmentation.h
new file mode 100644
index 0000000..6aa337e
--- /dev/null
+++ b/RayPlatform/memory/ChunkAllocatorWithDefragmentation.h
@@ -0,0 +1,106 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _ChunkAllocatorWithDefragmentation_H
+#define _ChunkAllocatorWithDefragmentation_H
+
+#include <memory/DefragmentationGroup.h>
+#include <memory/DefragmentationLane.h>
+#include <stdlib.h>
+
+/**
+ * basically, a SmartPointer is just an handle
+ * that can be resolved by some other object.
+ * The underlying location can change, but the SmartPointer
+ * does not change.
+ *
+ * A SmartPointer is transformed into a void* by ChunkAllocatorWithDefragmentation::getPointer()
+ * getPointer actually just asks the appropriate DefragmentationGroup
+ * by polling the array of DefragmentationLane objects.
+ */
+typedef uint32_t SmartPointer;
+
+/**
+ * This SmartPointer is the equivalent of NULL
+ */
+#define SmartPointer_NULL 4294967295u /* this is the maximum value for uint32_t */
+
+#define NUMBER_OF_LANES 512
+
+/**
+ * This ChunkAllocatorWithDefragmentation  allocate memory with
+ * a SmartPointer.
+ * Inside, a SmartPointer is translated to a SmallSmartPointer and given to
+ * the correct DefragmentationGroup in the  correct DefragmentationLane.
+ * \author Sébastien Boisvert
+ */
+class ChunkAllocatorWithDefragmentation{
+	DefragmentationLane*m_fastLane;
+	int m_numberOfLanes;
+
+	/** anxiliary table used by defragment() */
+	uint16_t*m_cellContents;
+	/** anxiliary table used by defragment() */
+	uint8_t*m_cellOccupancies;
+
+	/** show memory allocations */
+	bool m_show;
+
+	/** the size in bytes of an element   */
+	int m_bytesPerElement;
+
+	/** the first DefragmentationLane  */
+	DefragmentationLane*m_defragmentationLanes[NUMBER_OF_LANES];
+
+	/** update the fast lane */
+	void updateFastLane(int n);
+public:
+	/**
+ * print allocator information
+ */
+	void print();
+	/** clear allocations */
+	void destructor();
+
+	/** initialize a ChunkAllocatorWithDefragmentation  */
+	void constructor(int period,bool show);
+
+/**
+ * allocate memory
+ */
+	SmartPointer allocate(int s);
+
+/**
+ * free a SmartPointer
+ */
+	void deallocate(SmartPointer a);
+
+/**
+ * resolve a SmartPointer
+ */
+	void*getPointer(SmartPointer a);
+
+	ChunkAllocatorWithDefragmentation();
+	~ChunkAllocatorWithDefragmentation();
+
+	void defragment();
+};
+
+#endif
diff --git a/RayPlatform/memory/DefragmentationGroup.cpp b/RayPlatform/memory/DefragmentationGroup.cpp
new file mode 100644
index 0000000..996870b
--- /dev/null
+++ b/RayPlatform/memory/DefragmentationGroup.cpp
@@ -0,0 +1,648 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+/* TODO:  replace calls to Malloc by a single call to Malloc */
+/* TODO: replace m_allocatedSizes with a bitmap */
+
+/* run low-level assertions, pretty slow but that helped for the development. */
+/* even if ASSERT is defined, the low-level assertions are not */
+/* compiled unless LOW_LEVEL_ASSERT is defined */
+
+/* #define LOW_LEVEL_ASSERT */
+
+#include <memory/DefragmentationGroup.h>
+#include <memory/allocator.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+using namespace std;
+
+#ifdef  ASSERT
+#include <assert.h>
+#endif
+
+/** bit encoding  in the bit array */
+#define AVAILABLE 0
+#define UTILISED 1
+
+/** value for an occupied chunk in the array */
+#define BUSY_CHUNK 18446744073709551615UL
+
+
+/**
+ *  Return true if the DefragmentationGroup can allocate n elements 
+ *  Time complexity: O(1)
+ */
+bool DefragmentationGroup::canAllocate(int n){
+	/* we want fast allocation in the end...  
+	if a contiguous segment is not available, we can't handle it... 
+*/
+	#ifdef ASSERT
+	assert((ELEMENTS_PER_GROUP-m_freeSliceStart)<=m_availableElements);
+	#endif
+
+	return (ELEMENTS_PER_GROUP-m_freeSliceStart)>=n;
+}
+
+/**
+ *    fragmented slice             free slice
+ * |---------------------------|---------------|
+ *
+ *                             ^               ^
+ *                             |               |
+ * 0                           |            ELEMENTS_PER_GROUP-1
+ *                             |
+ *                     m_freeSliceStart
+ *
+ *  fragmented slice:  
+ *
+ *      part of m_block that will undergo fragmentation and defragmentation
+ *
+ *  free slice:
+ *      part of m_block that has no fragmentation
+ *      free slice has (ELEMENTS_PER_GROUP-m_freeSliceStart) consecutive AVAILABLE elements
+ *      starting at m_freeSliceStart
+ *
+ *  m_freeSliceStart:
+ *      indicates where the free slice begins
+ *      
+ *      Allocation algorithm:
+ *
+ * First, we try to find n consecutive AVAILABLE elements in the
+ * fragmented slice.
+ * This is O(ELEMENTS_PER_GROUP), and is a read-only operation, thus pretty fast.
+ *
+ * 64-element chunks that are filled completely are just not investigated.
+ * 
+ * This will defragment the fragmented slice and make the free slice
+ * larger.
+ * AVAILABLE elements.
+ *
+ *
+ * At first, we must obtain a free handle.
+ * This is usually O(256) if there is someone in m_fastPointers available.
+ * Otherwise, populating m_fastPointers is O(ELEMENTS_PER_GROUP)
+ *
+ */
+SmallSmartPointer DefragmentationGroup::allocate(int n,
+	int bytesPerElement,uint16_t*cellContents,uint8_t*cellOccupancies){
+
+	m_operations[__OPERATION_ALLOCATE]++;
+
+	/* verify pre-conditions */
+	#ifdef ASSERT
+	assert(n>0);
+	assert(canAllocate(n));
+	assert(n<=ELEMENTS_PER_GROUP);
+	assert(n<=m_availableElements);
+	assert(n<=(ELEMENTS_PER_GROUP-m_freeSliceStart));
+	assert(m_allocatedOffsets!=NULL);
+	assert(m_allocatedSizes!=NULL);
+	#endif
+
+/** 
+ * get an handle 
+ * This is O(256) if an available handle is found in m_fastPointers
+ * Otherwise, it is O(65536) -- but the worst case is actually very rare.
+ * */
+	SmallSmartPointer returnValue=getAvailableSmallSmartPointer();
+
+	/* make sure that this handle is not used already */
+	#ifdef ASSERT
+	assert(m_allocatedSizes[returnValue]==0);
+	#endif
+
+	/** save meta-data for the SmallSmartPointer */
+	m_allocatedOffsets[returnValue]=m_freeSliceStart;
+	m_allocatedSizes[returnValue]=n;
+
+	/** make sure that the meta-data was stored correctly */
+	#ifdef ASSERT
+	assert(m_allocatedSizes[returnValue]==n);
+	assert(m_allocatedOffsets[returnValue]==m_freeSliceStart);
+	#endif
+
+	/** move the frontier */
+	m_freeSliceStart+=n;
+
+	/** assert that all things on the right of the frontier **/
+	/* are freed */
+	#ifdef LOW_LEVEL_ASSERT
+	for(int i=m_freeSliceStart;i<ELEMENTS_PER_GROUP;i++){
+		if(getBit(i)!=AVAILABLE){
+			cout<<"Error, offset "<<i<<" is not AVAILABLE, allocated "<<n<<" at offset "<<offset<<"  m_freeSliceStart="<<m_freeSliceStart<<endl;
+			print();
+		}
+		assert(getBit(i)==AVAILABLE);
+	}
+	#endif
+
+	/* since we allocated n elements */
+	/* we have n less elements left */
+	m_availableElements-=n;
+	
+	// make sure that the number of available elements
+	// is valid
+	#ifdef ASSERT
+	if(m_availableElements<0)
+		cout<<"m_availableElements "<<m_availableElements<<endl;
+	assert(m_availableElements>=0);
+	assert(m_availableElements<=ELEMENTS_PER_GROUP);
+	#endif
+
+	__triggerDefragmentationRoutine(bytesPerElement,cellContents,cellOccupancies);
+
+	// finally return safely the handle
+	return returnValue;
+}
+
+/**
+ * Usually very fast, getAvailableSmallSmartPointer returns a SmallSmartPointer
+ * that is available. To do so, the list m_fastPointers is searched.
+ * This list contains FAST_POINTERS entries (default is 256).
+ * If there is a hit, it is returned to the caller.
+ * 
+ * Otherwise, all the possible SmallSmartPointer handles are probed
+ * (there are ELEMENTS_PER_GROUP (default is 65536) of them)
+ * and those available are appended to m_fastPointers.
+ * 
+ * Finally, the SmallSmartPointer that was the last to be recorded to m_fastPointers
+ * is returned.
+ *
+ * Time complexity: O(256) if an handle is available in m_fastPointers
+ * O(ELEMENTS_PER_GROUP) otherwise
+ */
+SmallSmartPointer DefragmentationGroup::getAvailableSmallSmartPointer(){
+	/* try to find a handle in the fast pointers */
+	/* O(FAST_POINTERS), FAST_POINTERS = 256 I think */
+	for(int i=0;i<FAST_POINTERS;i++)
+		if(m_allocatedSizes[m_fastPointers[i]]==0) /** it is available ! */
+			return m_fastPointers[i];
+
+	/**
+ * 	Otherwise, populate m_fastPointers
+ *  find an alternative available handle */
+	/** O(65536) */
+
+	SmallSmartPointer returnValue=0;
+
+	// populate fast pointers
+	// purge fast pointers that are allocated
+	int fast=0;
+	while(m_allocatedSizes[m_fastPointers[fast]]==0 && fast<FAST_POINTERS)
+		fast++;
+
+	int i=0;
+
+	// populate fast pointers
+	// with available handles
+	// O(ELEMENTS_PER_GROUP), ELEMENTS_PER_GROUP= 65536
+	for(i=0;i<ELEMENTS_PER_GROUP;i++){
+		if(m_allocatedSizes[i]==0){
+			m_fastPointers[fast++]=i;
+			/* always update returnValue to return the last one observed */
+			/* otherwise, if the first one is returned, it will be useless */
+			/* as a fast pointer */
+
+			/* TODO: possibly set returnValue to a handle that is not a fast pointer if possible */
+			
+			returnValue=i;
+		}
+
+		// add the fast pointer
+		while(m_allocatedSizes[m_fastPointers[fast]]==0 && fast<FAST_POINTERS)
+			fast++;
+
+		/** we populated m_fastPointers */
+		/** we can stop now **/
+		if(fast==FAST_POINTERS)
+			break;
+	}
+
+	/* return a handle */
+	return returnValue;
+}
+
+/**
+ * deallocate a SmallSmartPointer
+ * defragment
+ * done.
+ *
+ * Time complexity: O(n) when< CONFIG_DEFRAGMENTATION_THRESHOLD elements are in the fragmented zone
+ * Otherwise, O(ELEMENTS_PER_GROUP) for the call to defragment()
+ */
+void DefragmentationGroup::deallocate(SmallSmartPointer a,int bytesPerElement,uint16_t*cellContent,
+	uint8_t*cellOccupancies){
+
+	m_operations[__OPERATION_DEALLOCATE]++;
+
+	#ifdef LOW_LEVEL_ASSERT
+	assert((ELEMENTS_PER_GROUP-m_freeSliceStart)<=m_availableElements);
+	for(int i=m_freeSliceStart;i<ELEMENTS_PER_GROUP;i++){
+		if(getBit(i)!=AVAILABLE){
+			cout<<"Error, offset "<<i<<" is not AVAILABLE"<<endl;
+			print();
+		}
+		assert(getBit(i)==AVAILABLE);
+	}
+	#endif
+
+	#ifdef ASSERT
+	if(m_allocatedSizes[a]==0)
+		cout<<__func__<<" SmallSmartPointer "<<(int)a<<" has size 0."<<endl;
+	assert(m_allocatedSizes[a]>0);
+	#endif
+
+	// fetch meta-data
+	int allocatedSize=m_allocatedSizes[a];
+	int offset=m_allocatedOffsets[a];
+
+	/** set the size to 0 for this SmallSmartPointer */
+	m_allocatedSizes[a]=0;
+
+	// this is a special case
+	/* in which the region touches the frontier */
+	if(offset+allocatedSize==m_freeSliceStart){
+		m_freeSliceStart=offset;
+	}
+
+	#ifdef LOW_LEVEL_ASSERT
+	for(int i=m_freeSliceStart;i<ELEMENTS_PER_GROUP;i++){
+		if(getBit(i)!=AVAILABLE){
+			cout<<"Error, offset "<<i<<" is not AVAILABLE"<<endl;
+			print();
+		}
+		assert(getBit(i)==AVAILABLE);
+	}
+	#endif
+
+	#ifdef LOW_LEVEL_ASSERT
+	assert(m_allocatedSizes[a]==0);
+	#endif
+	
+	/* we have more elements available now */
+	m_availableElements+=allocatedSize;
+
+	#ifdef ASSERT
+	assert(m_availableElements<=ELEMENTS_PER_GROUP);
+	assert(m_availableElements>=0);
+	if(!((ELEMENTS_PER_GROUP-m_freeSliceStart)<=m_availableElements))
+		cout<<"elements in freeSlice: "<<ELEMENTS_PER_GROUP-m_freeSliceStart<<" available "<<m_availableElements<<" m_freeSliceStart "<<m_freeSliceStart<<endl;
+	assert((ELEMENTS_PER_GROUP-m_freeSliceStart)<=m_availableElements);
+	#endif
+
+	__triggerDefragmentationRoutine(bytesPerElement,cellContent,cellOccupancies);
+}
+
+/**
+ * Kick-start a DefragmentationGroup.
+ *
+ * Time complexity: O(1)
+ */
+void DefragmentationGroup::constructor(int bytesPerElement,bool show){
+
+	m_operations[__OPERATION_ALLOCATE]=0;
+	m_operations[__OPERATION_DEALLOCATE]=0;
+	m_operations[__OPERATION_DEFRAGMENT]=0;
+	
+	#ifdef ASSERT
+	assert(m_block==NULL);
+	#endif
+
+	m_availableElements=ELEMENTS_PER_GROUP;
+	
+	#ifdef ASSERT
+	assert(m_availableElements<=ELEMENTS_PER_GROUP);
+	assert(m_availableElements>=0);
+	#endif
+	
+	for(int i=0;i<FAST_POINTERS;i++)
+		m_fastPointers[i]=i;
+
+	m_freeSliceStart=0;
+	/** allocate the memory */
+	m_block=(uint8_t*)__Malloc(ELEMENTS_PER_GROUP*bytesPerElement,"RAY_MALLOC_TYPE_DEFRAG_GROUP",show);
+
+	/** initialise sizes */
+	m_allocatedSizes=(uint8_t*)__Malloc(ELEMENTS_PER_GROUP*sizeof(uint8_t),"RAY_MALLOC_TYPE_DEFRAG_GROUP",show);
+	m_allocatedOffsets=(uint16_t*)__Malloc(ELEMENTS_PER_GROUP*sizeof(uint16_t),"RAY_MALLOC_TYPE_DEFRAG_GROUP",show);
+	
+	for(int i=0;i<ELEMENTS_PER_GROUP;i++){
+		m_allocatedSizes[i]=0;
+		m_allocatedOffsets[i]=0;
+	}
+
+	#ifdef ASSERT
+	assert((ELEMENTS_PER_GROUP-m_freeSliceStart)<=m_availableElements);
+	#endif
+}
+
+/**
+ * Free memory
+ */
+void DefragmentationGroup::destructor(bool show){
+	__Free(m_block,"RAY_MALLOC_TYPE_DEFRAG_GROUP",show);
+	m_block=NULL;
+	__Free(m_allocatedSizes,"RAY_MALLOC_TYPE_DEFRAG_GROUP",show);
+	m_allocatedSizes=NULL;
+	__Free(m_allocatedOffsets,"RAY_MALLOC_TYPE_DEFRAG_GROUP",show);
+	m_allocatedOffsets=NULL;
+}
+
+/**
+ * Resolvee a SmallSmartPointer
+ */
+void*DefragmentationGroup::getPointer(SmallSmartPointer a,int bytesPerElement){
+	#ifdef ASSERT
+	if(m_allocatedSizes[a]==0)
+		cout<<"this= "<<this<<" can not getPointer on SmallSmartPointer "<<(int)a<<" because it is not allocated."<<endl;
+	assert(m_allocatedSizes[a]!=0);
+	#endif
+	int offset=m_allocatedOffsets[a];
+	void*pointer=m_block+offset*bytesPerElement;
+	return pointer;
+}
+
+/**
+ * Set pointers to NULL
+ */
+void DefragmentationGroup::setPointers(){
+	m_block=NULL;
+	m_allocatedOffsets=NULL;
+	m_allocatedSizes=NULL;
+}
+
+/**
+ * Check if the DefragmentationGroup is active.
+ */
+bool DefragmentationGroup::isOnline(){
+	return m_block!=NULL;
+}
+
+/**
+ * Get the number of available elements
+ */
+int DefragmentationGroup::getAvailableElements(){
+	#ifdef ASSERT
+	assert(m_block!=NULL);
+	assert(m_availableElements<=ELEMENTS_PER_GROUP);
+	assert(m_availableElements>=0);
+	#endif
+	return m_availableElements;
+}
+
+void DefragmentationGroup::print(){
+}
+
+int DefragmentationGroup::getFreeSliceStart(){
+	return m_freeSliceStart;
+}
+
+/**
+ * defragmentation is O(ELEMENTS_PER_GROUP)
+ * there is a frontier called m_freeSliceStart
+ * on the left, things are fragmented
+ * on the right, things are free and nothing is allocated
+ * What this code does is just linearly compact the gaps
+ * from left to right
+ * while doing so, meta-data
+ * are moved correctly.
+ * \author Sébastien Boisvert
+ */
+
+#define __defragment_optimized
+bool DefragmentationGroup::defragment(int bytesPerElement,uint16_t*cellContents,uint8_t*cellOccupancies){
+
+
+	m_operations[__OPERATION_DEFRAGMENT]++;
+
+	#ifdef __defragment_optimized
+
+	memset(cellOccupancies,0x0,ELEMENTS_PER_GROUP);
+
+	#else
+
+	/* update the look-up table */
+	for(int i=0;i<ELEMENTS_PER_GROUP;i++){
+		cellOccupancies[i]=0;
+	}
+
+	#endif
+
+	
+	for(int i=0;i<ELEMENTS_PER_GROUP;i++){
+		/* otherwise we don't want to register it because it may overwrite someone else */
+		if(m_allocatedSizes[i]!=0){
+			cellContents[m_allocatedOffsets[i]]=i;
+			for(int j=0;j<m_allocatedSizes[i];j++)
+				cellOccupancies[m_allocatedOffsets[i]+j]=1;
+		}
+	}
+
+	#ifdef ASSERT
+	assert((ELEMENTS_PER_GROUP-m_freeSliceStart)<=m_availableElements);
+	#endif
+
+	/* nothing is available */
+	if(m_availableElements==0)
+		return false;
+
+	/* everything is already in the free slice */
+	int elementsInFreeSlice=ELEMENTS_PER_GROUP-m_freeSliceStart;
+	if(m_availableElements==elementsInFreeSlice)
+		return false;
+
+	int destination=0;
+	int source=0;
+
+	// skip allocated stuff.
+	while(cellOccupancies[destination]==1 && destination<ELEMENTS_PER_GROUP)
+		destination++;
+
+	source=destination+1;
+
+	while(cellOccupancies[source]==0 && source<ELEMENTS_PER_GROUP)
+		source++;
+
+	while(source<ELEMENTS_PER_GROUP){
+		/* if source is empty, we are done. */
+		if(cellOccupancies[source]==0)
+			break;
+
+		/* at this point, source points to a offset where a SmallSmartPointer starts */
+		/* and destination is an empty space. */
+		#ifdef ASSERT
+		if(!(source>destination)){
+			cout<<"destination "<<destination<<" source "<<source<<endl;
+			print();
+		}
+		assert(source>destination);
+		#endif
+
+		#ifdef ASSERT
+		assert(cellOccupancies[destination]==0);
+		assert(cellOccupancies[source]==1);
+		#endif
+
+		/* here we copy source in destination */
+		/* copy the data */
+		SmallSmartPointer smartPointer=cellContents[source];
+
+		#ifdef ASSERT
+		assert(cellOccupancies[source-1]==0);
+		if(!(m_allocatedSizes[smartPointer]!=0)){
+			cout<<"SmallSmartPointer "<<smartPointer<<" must move, but is has size 0 and bit is 1"<<endl;
+			print();
+		}
+		assert(m_allocatedSizes[smartPointer]!=0);
+		#endif
+		
+		int n=m_allocatedSizes[smartPointer];
+		for(int i=0;i<n;i++){
+			for(int byte=0;byte<bytesPerElement;byte++){
+				m_block[(destination+i)*bytesPerElement+byte]=m_block[(source+i)*bytesPerElement+byte];
+			
+			}
+		}
+
+		#ifdef __defragment_optimized
+
+		if(n>0)
+			memset(cellOccupancies+destination,0x1,n);
+		
+		int count=source-destination;
+
+		if(count>0)
+			memset(cellOccupancies+destination+n,0x0,count);
+
+		#else
+
+		for(int i=destination;i<destination+n;i++)
+			cellOccupancies[i]=1;
+
+		for(int i=destination+n;i<source+n;i++)
+			cellOccupancies[i]=0;
+
+		#endif
+
+		m_allocatedOffsets[smartPointer]=destination;
+
+		/* move destination after the new location of smartPointer */
+		destination+=n;
+		source+=n;
+
+		/* skip occupied elements */
+		while(cellOccupancies[destination]==1 && destination<ELEMENTS_PER_GROUP)
+			destination++;
+
+		/* now destination is at a free block */
+
+		/* skip available elements */
+		while(cellOccupancies[source]==0 && source<ELEMENTS_PER_GROUP)
+			source++;
+	}
+	
+	m_freeSliceStart=destination;
+
+	#ifdef ASSERT
+	assert((ELEMENTS_PER_GROUP-m_freeSliceStart)<=m_availableElements);
+	#endif
+
+	#ifdef LOW_LEVEL_ASSERT
+	for(int i=m_freeSliceStart;i<ELEMENTS_PER_GROUP;i++)
+		assert(getBit(i)==AVAILABLE);
+
+	for(int i=0;i<m_freeSliceStart;i++)
+		assert(getBit(i)==UTILISED);
+
+	int bitTo1=0;
+	int elements=0;
+	for(int i=0;i<ELEMENTS_PER_GROUP;i++){
+		bitTo1+=getBit(i);
+		if(m_allocatedSizes[i]!=0){
+			if(!(m_allocatedOffsets[i]<m_freeSliceStart)){
+				cout<<"SmallSmartPointer "<<i<<" has offset is "<<m_allocatedOffsets[i]<<" but m_freeSliceStart is "<<m_freeSliceStart<<" size: "<<(int)m_allocatedSizes[i]<<endl;
+				print();
+			}
+			assert(m_allocatedOffsets[i]<m_freeSliceStart);
+			elements+=m_allocatedSizes[i];
+			for(int j=0;j<m_allocatedSizes[i];j++){
+				if(!(getBit(m_allocatedOffsets[i]+j)==UTILISED)){
+					cout<<"Error, SmallSmartPointer "<<i<<" offset "<<(int)m_allocatedOffsets[i]<<" size "<<(int)m_allocatedSizes[i]<<" is not in the bitmap at j="<<j<<endl;
+					print();
+				}
+				assert(getBit(m_allocatedOffsets[i]+j)==UTILISED);
+			}
+		}
+	}
+	assert(bitTo1==elements);
+	#endif
+
+	return true;
+}
+
+#undef __defragment_optimized
+
+void DefragmentationGroup::__triggerDefragmentationRoutine(int bytesPerElement,uint16_t*cellContents,
+	uint8_t*cellOccupancies){
+
+	int elementsInFreeSlice=getContiguousElements();
+	int fragmentedElements=getFragmentedElements();
+
+	/** this threshold is the minimum number of bins in the fragmented zone
+ * 	that are necessary to trigger a defragmentation 
+ *	low value will trigger a lot of defragmentation events, but defragmentation
+ *	is kind of slow. Therefore, you want a amortized time complexity -- that is
+ *	in general we don't defragment (fast), but sometimes we do (slow)
+ *	many fast events plus a few slow events is hopefully more fast than slow.
+ *
+ *	\date 2012-08-09 if there are still some good stuff
+ * 	*/
+
+	/** the main client of this code is the hash table */
+	/** the hash table allocates a maximum of 64 elements for a single call of allocate() **/
+
+	int thresholdForFragmentedWarZone=2048;
+	int thresholdForFreeSlice=128;
+
+	if(fragmentedElements>= thresholdForFragmentedWarZone
+		&& elementsInFreeSlice <= thresholdForFreeSlice )
+		defragment(bytesPerElement,cellContents,cellOccupancies);
+
+}
+
+int DefragmentationGroup::getFragmentedElements(){
+
+	int elementsInFreeSlice=getContiguousElements();
+	int fragmentedElements=m_availableElements-elementsInFreeSlice;
+
+	return fragmentedElements;
+}
+
+int DefragmentationGroup::getContiguousElements(){
+
+	int elementsInFreeSlice=ELEMENTS_PER_GROUP-m_freeSliceStart;
+
+	return elementsInFreeSlice;
+}
+
+int DefragmentationGroup::getOperations(int operationCode){
+	return m_operations[operationCode];
+}
diff --git a/RayPlatform/memory/DefragmentationGroup.h b/RayPlatform/memory/DefragmentationGroup.h
new file mode 100644
index 0000000..f557e8b
--- /dev/null
+++ b/RayPlatform/memory/DefragmentationGroup.h
@@ -0,0 +1,166 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _DefragmentationGroup_H
+#define _DefragmentationGroup_H
+
+/* 
+ * How many elements per group ?
+ * this is the number of values of uint16_t */
+#define ELEMENTS_PER_GROUP 65536 
+
+/**
+ * Number of fast pointers
+ * Fast pointers is a list of SmallSmartPointer that can be used.
+ */
+#define FAST_POINTERS 256
+
+#include <stdint.h>
+
+/**
+ * A SmallSmartPointer is a smart pointer than only a DefragmentationGroup
+ * can resolve.
+ */
+typedef uint16_t SmallSmartPointer;
+
+#define __OPERATION_ALLOCATE 0x0
+#define __OPERATION_DEALLOCATE 0x1
+#define __OPERATION_DEFRAGMENT 0x2
+
+
+/**
+ * This class does the complex logic
+ * for memory allocation and deallocation,
+ * including defragmentation using compacting
+ * \author Sébastien Boisvert
+ */
+class DefragmentationGroup{
+
+	int m_operations[__OPERATION_DEFRAGMENT+1];
+
+	/** routine to test if we must run defragmentation **/
+
+	void __triggerDefragmentationRoutine (int bytesPerElement,uint16_t*cellContent,
+		uint8_t*cellOccupancies) ;
+
+	/** freed stuff to accelerate things. */
+	uint16_t m_fastPointers[FAST_POINTERS];
+	
+	/**
+ * the number of available elements
+ */
+	int m_availableElements;
+
+	/** last free position */
+	int m_freeSliceStart;
+
+	/**
+ * 	Pointer to allocated memory
+ * 	65536 * 18 = 1179648 bytes 
+ */
+	uint8_t*m_block;
+
+	/**
+ * 	the sizes range from 0 to 64
+ * 	using a uint8_t for each SmallSmartPointer
+ * 	65536 * 1 = 65536 bytes
+ */
+	uint8_t*m_allocatedSizes;
+
+	/**
+ * 	the offsets
+ * 	these will change during defragmentation
+ * 	128 KiB
+ */
+	uint16_t*m_allocatedOffsets;
+
+/** print the bitmap
+ */
+	void print();
+
+/**
+ * get a SmallSmartPointer
+ */
+	SmallSmartPointer getAvailableSmallSmartPointer();
+	
+/*
+ * returns true if defragmented something. */
+	bool defragment(int bytesPerElement,uint16_t*cellContents,uint8_t*cellOccupancies);
+public:
+
+
+/**
+ * Initialize pointers to NULL
+ */
+	void setPointers();
+
+/** 
+ * Initialiaze DefragmentationGroup
+ */
+	void constructor(int bytesPerElement,bool show);
+
+/**
+ * Allocate memory
+ */
+	SmallSmartPointer allocate(int n,int bytesPerElement,uint16_t*cellContents,uint8_t*cellOccupancies);
+
+/**
+ * Free memory
+ * deallocate will defragment the block immediately
+ */
+	void deallocate(SmallSmartPointer a,int bytesPerElement,uint16_t*cellContents,uint8_t*cellOccupancies);
+/** 
+ * destroy the allocator
+ */
+	void destructor(bool show);
+
+/**
+ * can the allocator allocate n elements ?
+ */
+	bool canAllocate(int n);
+
+	/**
+ * 	translate a SmallSmartPointer to an actual pointer
+ */
+	void*getPointer(SmallSmartPointer a,int bytesPerElement);
+	
+	/**
+ * 	return yes if activated
+ */
+	bool isOnline();
+
+/**
+ * return the number of available elements 
+ */
+	int getAvailableElements();
+
+/** get the frontier **/
+	int getFreeSliceStart();
+
+/** get the number of available elements left of the frontier **/
+	int getFragmentedElements();
+
+/** get the number of available elements in the free slice **/
+	int getContiguousElements();
+
+	int getOperations(int operationCode);
+};
+
+#endif
diff --git a/RayPlatform/memory/DefragmentationLane.cpp b/RayPlatform/memory/DefragmentationLane.cpp
new file mode 100644
index 0000000..89578a3
--- /dev/null
+++ b/RayPlatform/memory/DefragmentationLane.cpp
@@ -0,0 +1,157 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#include <memory/DefragmentationLane.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <iostream>
+using namespace std;
+
+/**
+ * Time complexity: O(GROUPS_PER_LANE) to initializing DefragmentationGroup objects 
+ */
+void DefragmentationLane::constructor(int number,int ,bool ){
+	m_number=number;
+	for(int i=0;i<GROUPS_PER_LANE;i++)
+		m_groups[i].setPointers();
+
+	m_fastGroup=INVALID_GROUP;
+	m_numberOfActiveGroups=0;
+	m_numberOfFastGroups=0;
+}
+
+/** Update m_fastGroup rapidly */
+void DefragmentationLane::getFastGroup(int n,int bytesPerElement,bool show){
+	/* if m_fastGroup can allocate n elements, use it right away
+	Time complexity:  O(1) */
+	if(m_fastGroup!=INVALID_GROUP && m_groups[m_fastGroup].canAllocate(n))
+		return;
+
+	/* try to find the fast group in the list m_fastGroups
+	Time complexity: O(NUMBER_OF_FAST_GROUPS) (default=128)*/
+	for(int i=0;i<m_numberOfFastGroups;i++){
+		if(m_fastGroups[i]!=INVALID_GROUP && m_groups[m_fastGroups[i]].canAllocate(n)){
+			m_fastGroup=m_fastGroups[i];
+			return;
+		}
+	}
+
+	/* update m_fastGroups using the m_numberOfActiveGroups DefragmentationGroup objects 
+	Time complexity: O(m_numberOfActiveGroups) where m_numberOfActiveGroups <= GROUPS_PER_LANE */
+	int target=64;
+	m_numberOfFastGroups=0;
+	int group=0;
+
+	while(m_numberOfFastGroups<NUMBER_OF_FAST_GROUPS && group<m_numberOfActiveGroups){
+		if(m_groups[group].canAllocate(target))
+			m_fastGroups[m_numberOfFastGroups++]=group;
+		group++;
+	}
+		
+	/* if there is at least 1 fast group */
+	if(m_numberOfFastGroups>0){
+		m_fastGroup=m_fastGroups[0];
+		return;
+	}
+
+	/* no more group can be created and therefore the DefragmentationLane is too busy */
+	if(m_numberOfActiveGroups==GROUPS_PER_LANE){
+		m_fastGroup=INVALID_GROUP;
+		#ifdef ASSERT
+		assert(m_numberOfFastGroups==0);
+		#endif
+		return;
+	}
+
+	/** activate a DefragmentationGroup */
+	m_groups[m_numberOfActiveGroups].constructor(bytesPerElement,show);
+
+	/* there is only 1 one fast group */
+	m_fastGroups[m_numberOfFastGroups]=m_numberOfActiveGroups;
+	m_fastGroup=m_fastGroups[0];
+	m_numberOfActiveGroups++;
+	m_numberOfFastGroups++;
+
+	#ifdef ASSERT
+	assert(m_numberOfFastGroups==1);
+	#endif
+
+	return;
+}
+
+/**
+ * can the DefragmentationLane allocates rapidly n elements ? 
+ * Time complexity: O(1) if m_fastGroup can deliver
+ * otherwise, O(GROUPS_PER_LANE)
+ * */
+bool DefragmentationLane::canAllocate(int n,int bytesPerElement,bool show){
+	if(m_fastGroup!=INVALID_GROUP)
+		if(m_groups[m_fastGroup].canAllocate(n))
+			return true;
+
+	getFastGroup(n,bytesPerElement,show);
+	return m_fastGroup!=INVALID_GROUP;
+}
+
+/**
+ * Time complexity: O(1)
+ */
+SmallSmartPointer DefragmentationLane::allocate(int n,int bytesPerElement,int*group,
+uint16_t*cellContents,
+	uint8_t*cellOccupancies ){
+
+	#ifdef ASSERT
+	assert(m_fastGroup!=-1);
+	if(!(m_fastGroup<GROUPS_PER_LANE))
+		cout<<"m_fastGroup= "<<m_fastGroup<<endl;
+	assert(m_fastGroup<GROUPS_PER_LANE);
+	assert(m_fastGroup>=0);
+	assert(n>0);
+	assert(bytesPerElement>0);
+	assert(group!=NULL);
+	assert(m_fastGroup!=INVALID_GROUP);
+	assert(m_fastGroup<m_numberOfActiveGroups);
+	#endif
+
+	// the fast group is always valid
+	// this is an invariant
+	(*group)=m_fastGroup;
+
+	return m_groups[m_fastGroup].allocate(n,
+		bytesPerElement,cellContents,cellOccupancies
+		);
+}
+
+/**
+ * Time complexity: O(1)
+ */
+int DefragmentationLane::getNumber(){
+	return m_number;
+}
+
+/**
+ * Time complexity: O(1)
+ */
+DefragmentationGroup*DefragmentationLane::getGroup(int i){
+	#ifdef ASSERT
+	assert(i<GROUPS_PER_LANE);
+	#endif
+	return m_groups+i;
+}
diff --git a/RayPlatform/memory/DefragmentationLane.h b/RayPlatform/memory/DefragmentationLane.h
new file mode 100644
index 0000000..dcf3d1c
--- /dev/null
+++ b/RayPlatform/memory/DefragmentationLane.h
@@ -0,0 +1,92 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _DefragmentationLane_H
+#define _DefragmentationLane_H
+
+#include <memory/DefragmentationGroup.h>
+
+/** value for a invalid DefragmentationGroup */
+#define INVALID_GROUP 123467
+
+/** 
+ * the number of DefragmentationGroup per DefragmentationLane
+ */
+#define GROUPS_PER_LANE 1024
+
+/** the number of DefragmentationGroup */
+#define NUMBER_OF_FAST_GROUPS 128
+
+/**
+ * A SmartPointer maps to a SmallSmartPointer inside
+ * a DefragmentationGroup
+ *
+ * A DefragmentationGroup is in a DefragmentationLane.
+ * A DefragmentationLane contains GROUPS_PER_LANE DefragmentationGroup.
+ * \author Sébastien Boisvert
+ */
+class DefragmentationLane{
+	/** the identifier of the DefragmentationLane */
+	int m_number;
+
+	/** list of DefragmentationGroup */
+	DefragmentationGroup m_groups[GROUPS_PER_LANE];
+
+	/** fast DefragmentationGroup objects */
+	int m_fastGroups[NUMBER_OF_FAST_GROUPS];
+
+	/** the fastest DefragmentationGroup object */
+	int m_fastGroup;
+
+	/** the number of active DefragmentationGroup objects */
+	int m_numberOfActiveGroups;
+
+	/** the number of fast DefragmentationGroup objects */
+	int m_numberOfFastGroups;
+
+	/** update m_fastGroup, if no DefragmentationGroup can allocate n elements, then m_fastGroup is set
+	 to INVALID_GROUP */
+	void getFastGroup(int n,int bytesPerElement,bool show);
+public:
+	/** allocate a SmallSmartPointer */
+	SmallSmartPointer allocate(int n,int bytesPerElement,int*group,
+uint16_t*cellContent,
+	uint8_t*cellOccupancies 
+);
+
+	/** initialize the DefragmentationLane */
+	void constructor(int number,int bytesPerElement,bool show);
+
+	/** can the DefragmentationLane allocate n elements ? */
+	bool canAllocate(int n,int bytesPerElement,bool show);
+
+	/** return memory to the pool */
+	void deallocate(SmallSmartPointer a);
+
+	/** get the identifier of the DefragmentationLane */
+	int getNumber();
+
+	/** get a DefragmentationGroup directly */
+	DefragmentationGroup*getGroup(int i);
+
+};
+
+
+#endif
diff --git a/RayPlatform/memory/MyAllocator.cpp b/RayPlatform/memory/MyAllocator.cpp
new file mode 100644
index 0000000..7643ef8
--- /dev/null
+++ b/RayPlatform/memory/MyAllocator.cpp
@@ -0,0 +1,183 @@
+/*
+ 	Ray
+    Copyright (C)  2010  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <memory/allocator.h>
+#include <memory/MyAllocator.h>
+#include <stdlib.h>
+#include <core/OperatingSystem.h>
+#include <iostream>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h> /* for strcpy */
+using namespace std;
+
+/**
+ * reset the currentPosition and reuse allocated memory.
+ */
+void MyAllocator::reset(){
+	m_currentPosition=0;
+	m_currentChunkId=0;
+	m_store.reset();
+}
+
+/** the constructor does not allocate a chunk */
+void MyAllocator::constructor(int chunkSize,const char*type,bool show){
+	m_show=show;
+	m_CHUNK_SIZE=chunkSize; 
+	strcpy(m_type,type);
+}
+
+/**  add a chunk of memory */
+void MyAllocator::addChunk(){
+	void*currentChunk=(void*)__Malloc(m_CHUNK_SIZE,m_type,m_show);
+	#ifdef ASSERT
+	assert(currentChunk!=NULL);
+	#endif
+	m_chunks.push_back(currentChunk);
+	m_currentChunkId=0;
+	m_currentPosition=0;
+}
+
+/** this is a chunk allocator 
+ * when a chunk is consumed totally,
+ * a new one is created
+ */
+void*MyAllocator::allocate(int s){
+	#ifdef ASSERT
+	assert(s!=0);
+	#endif
+
+	/* reuse memory freed elsewhere */
+	if(m_store.hasAddressesToReuse(s))
+		return m_store.reuseAddress(s);
+
+	/* add a first chunk to the pool */
+	if(m_chunks.size()==0)
+		addChunk();
+
+	#ifndef FORCE_PACKING
+	// hopefully fix alignment issues on Itanium
+	int alignment=8;
+	if(s%8!=0){
+		s=roundNumber(s,alignment);
+	}
+	#ifdef ASSERT
+	assert(s%8==0);
+	#endif
+	#endif
+
+	#ifdef ASSERT
+	if(s>m_CHUNK_SIZE){
+		cout<<"Requested "<<s<<" -- only have "<<m_CHUNK_SIZE<<endl;
+	}
+	assert(s<=m_CHUNK_SIZE);
+	#endif
+	if(s>m_CHUNK_SIZE){
+		cout<<"Critical exception: The length of the requested memory exceeds the CHUNK_SIZE: "<<s<<" > "<<m_CHUNK_SIZE<<endl;
+		assert(false);
+		return NULL;// you asked too much.., this is critical..
+	}
+	
+	int left=m_CHUNK_SIZE-m_currentPosition;
+	if(s>left){
+		if(!(m_currentChunkId+1<(int)m_chunks.size())){
+			void*currentChunk=__Malloc(m_CHUNK_SIZE,m_type,m_show);
+			m_chunks.push_back(currentChunk);
+		}
+		m_currentChunkId++;
+		m_currentPosition=0;
+		return allocate(s);
+	}
+	
+	#ifdef ASSERT
+	if(m_currentChunkId>=(int)m_chunks.size()){
+		cout<<"ChunkId="<<m_currentChunkId<<" Chunks="<<m_chunks.size()<<endl;
+	}
+	
+	assert(m_currentChunkId<(int)m_chunks.size());
+	if(m_currentPosition>=m_CHUNK_SIZE){
+		cout<<"Error: ToAllocate="<<s<<" Chunks="<<m_chunks.size()<<" CurrentChunk="<<m_currentChunkId<<" ChunkPosition="<<m_currentPosition<<" ChunkSize="<<m_CHUNK_SIZE<<endl;
+		exit(EXIT_NO_MORE_MEMORY);
+	}
+	assert(m_currentPosition<m_CHUNK_SIZE);
+	#endif
+
+	// the address is the head of currentCHunk+ m_currentPosition bytes
+	void*r=(void*)(((char*)m_chunks[m_currentChunkId])+m_currentPosition);
+
+	// increase the current position.
+	m_currentPosition+=s;
+
+	#ifdef ASSERT
+	assert(m_currentPosition >= 0 && m_currentPosition <= m_CHUNK_SIZE);
+
+	/* make sure that we can dereference r and use s bytes */
+	char*test=(char*)r;
+	for(int i=0;i<s;i++){
+		test[i]=0;
+	}
+
+	#endif
+
+	return r;
+}
+
+MyAllocator::~MyAllocator(){}
+
+void MyAllocator::clear(){
+	m_store.reset();
+	for(int i=0;i<(int)m_chunks.size();i++){
+		__Free(m_chunks[i],m_type,m_show);
+	}
+	m_chunks.clear();
+	m_currentPosition=0;
+	m_currentChunkId=0;
+
+	m_store.reset();
+}
+
+int MyAllocator::getChunkSize(){
+	return m_CHUNK_SIZE;
+}
+
+void MyAllocator::print(){
+	cout<<"ChunkSize= "<<m_CHUNK_SIZE<<endl;
+	cout<<"AllocatedChunks= "<<m_chunks.size()<<endl;
+	cout<<"TotalBytesConsumed= "<<m_CHUNK_SIZE*m_chunks.size()<<endl;
+	m_store.print();
+}
+
+int MyAllocator::getNumberOfChunks(){
+	return m_chunks.size();
+}
+
+void MyAllocator::free(void*a,int b){
+	m_store.addAddressToReuse(a,b);
+}
+
+MyAllocator::MyAllocator(){
+}
+
+int roundNumber(int s,int alignment){
+	return ((s/alignment)+1)*alignment;
+}
+
+
diff --git a/RayPlatform/memory/MyAllocator.h b/RayPlatform/memory/MyAllocator.h
new file mode 100644
index 0000000..b13bbbc
--- /dev/null
+++ b/RayPlatform/memory/MyAllocator.h
@@ -0,0 +1,88 @@
+/*
+ 	Ray
+    Copyright (C)  2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _MyAllocator
+#define _MyAllocator
+
+#include <vector>
+#include <memory/ReusableMemoryStore.h>
+using namespace std;
+
+/**
+ * all memory allocations that are pervasive use this allocator.
+ * MyAllocator is a simple CHUNK_ALLOCATOR.
+ * it allocates m_CHUNK_SIZE bytes internally.
+ * when one requests memory, it uses this *chunk*.
+ * it the chunk gets depleted, MyAllocator renews a new one and store the depleted one in its internals.
+ * Also, MyAllocator reuses automatically memory freed with MyAllocator::free()
+ * \author Sébastien Boisvert
+ */
+class MyAllocator{
+	char m_type[101];
+	bool m_show;
+	vector<void*>m_chunks;
+	int m_currentPosition;
+	int m_currentChunkId;
+	int m_CHUNK_SIZE;
+
+/** garbage store, memory will be reused */
+	ReusableMemoryStore m_store;
+
+	void addChunk();
+
+public:
+	MyAllocator();
+	/**
+ * print allocator information
+ */
+	void print();
+	void clear();
+
+	/**
+ * assign a size to the allocator.
+ */
+	void constructor(int a,const char*type,bool show);
+
+/**
+ * allocate memory
+ */
+	void*allocate(int s);
+
+	~MyAllocator();
+	int getChunkSize();
+	int getNumberOfChunks();
+
+/**
+ * return the container for reusable memory
+ */
+	/**
+ 	* reset the chunk to reuse it properly.
+ 	*/
+	void reset();
+
+/** free memory */
+	void free(void*a,int b);
+};
+
+int roundNumber(int number,int alignment);
+
+
+#endif
diff --git a/RayPlatform/memory/ReusableMemoryStore.cpp b/RayPlatform/memory/ReusableMemoryStore.cpp
new file mode 100644
index 0000000..eba1dcf
--- /dev/null
+++ b/RayPlatform/memory/ReusableMemoryStore.cpp
@@ -0,0 +1,122 @@
+/*
+ 	Ray
+    Copyright (C)  2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <memory/ReusableMemoryStore.h>
+#include <iostream>
+#include <assert.h>
+using namespace std;
+
+void ReusableMemoryStore::constructor(){
+}
+
+/** returns true if size bytes can be allocated
+ * from the garbage stack
+ */
+bool ReusableMemoryStore::hasAddressesToReuse(int size){
+	bool test=m_toReuse.count(size)>0;
+	#ifdef ASSERT
+	if(test){
+		assert(m_toReuse[size]!=NULL);
+	}
+	#endif
+	return test;
+}
+
+void*ReusableMemoryStore::reuseAddress(int size){
+	#ifdef ASSERT
+	assert(m_toReuse.count(size)>0 && m_toReuse[size]!=NULL);
+	#endif
+
+	Element*tmp=m_toReuse[size];
+
+	#ifdef ASSERT
+	assert(tmp!=NULL);
+	#endif
+
+	Element*next=(Element*)tmp->m_next;
+	m_toReuse[size]=next;
+	if(m_toReuse[size]==NULL){
+		m_toReuse.erase(size);
+	}
+
+	#ifdef ASSERT
+	if(m_toReuse.count(size)>0){
+		assert(m_toReuse[size]!=NULL);
+	}
+	#endif
+
+	return tmp;
+}
+/**
+ * add size bytes to the garbage stack
+ */
+void ReusableMemoryStore::addAddressToReuse(void*p,int size){
+	/** don't free these tiny bits -- sizeof(Element) is 8 bytes on a 64-bit system */
+	if(size<(int)sizeof(Element)){
+		return;
+	}
+
+	#ifdef ASSERT
+	assert(p!=NULL);
+	#endif
+
+	Element*ptr=(Element*)p;
+	ptr->m_next=NULL;
+	if(m_toReuse.count(size)>0){
+		Element*next=m_toReuse[size];
+
+		#ifdef ASSERT
+		assert(next!=NULL);
+		#endif
+
+		ptr->m_next=next;
+	}
+	m_toReuse[size]=ptr;
+}
+
+void ReusableMemoryStore::reset(){
+	m_toReuse.clear();
+}
+
+void ReusableMemoryStore::print(){
+	cout<<"ReusableMemoryStore Information"<<endl;
+	int totalBytes=0;
+	for(map<int,Element*>::iterator i=m_toReuse.begin();
+		i!=m_toReuse.end();i++){
+		int bytes=i->first;
+		Element*ptr=i->second;
+		#ifdef ASSERT
+		assert(ptr!=NULL);
+		#endif
+		int count=0;
+		while(ptr!=NULL){
+			count++;
+			ptr=(Element*)ptr->m_next;
+		}
+		cout<<"("<<bytes<<": "<<count<<") ";
+		cout.flush();
+		totalBytes+=bytes*count;
+	}
+	cout<<endl;
+	cout<<"Total: "<<totalBytes/1024<<" KiB"<<endl;
+	cout.flush();
+
+}
diff --git a/RayPlatform/memory/ReusableMemoryStore.h b/RayPlatform/memory/ReusableMemoryStore.h
new file mode 100644
index 0000000..c49304c
--- /dev/null
+++ b/RayPlatform/memory/ReusableMemoryStore.h
@@ -0,0 +1,51 @@
+/*
+ 	Ray
+    Copyright (C)  2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _ReusableMemoryStore
+#define _ReusableMemoryStore
+
+#include <stdint.h>
+#include <map>
+using namespace std;
+
+typedef struct{
+	void*m_next;
+}Element;
+
+/** 
+ * the ReusableMemoryStore don't allocate much memory
+ * it bins freed chunks by size  and these are linked in list.
+ * The m_next pointer is actually in the freed chunk.
+ * \author Sébastien Boisvert
+ */
+class ReusableMemoryStore{
+	map<int,Element*> m_toReuse;
+public:
+
+	bool hasAddressesToReuse(int size);
+	void*reuseAddress(int size);
+	void addAddressToReuse(void*ptr,int size);
+	void constructor();
+	void reset();
+	void print();
+};
+
+#endif
diff --git a/RayPlatform/memory/RingAllocator.cpp b/RayPlatform/memory/RingAllocator.cpp
new file mode 100644
index 0000000..33ac7a9
--- /dev/null
+++ b/RayPlatform/memory/RingAllocator.cpp
@@ -0,0 +1,222 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <memory/RingAllocator.h>
+#include <memory/allocator.h>
+
+#include <string.h>
+#include <assert.h>
+#include <iostream>
+using namespace std;
+
+// #define CONFIG_RING_VERBOSE
+
+#define BUFFER_STATE_AVAILABLE 0x0
+#define BUFFER_STATE_DIRTY 0x1
+
+void RingAllocator::constructor(int chunks,int size,const char*type,bool show){
+
+	resetCount();
+
+	/* m_max should never be 0 */
+	#ifdef ASSERT
+	assert(size>0);
+	assert(chunks>0);
+	#endif /* ASSERT */
+
+	m_chunks=chunks;// number of buffers
+
+	m_max=size;// maximum buffer size in bytes
+
+	#ifdef ASSERT
+	assert(m_chunks==chunks);
+	assert(m_max==size);
+	#endif /* ASSERT */
+
+	strcpy(m_type,type);
+
+	m_numberOfBytes=m_chunks*m_max;
+
+	#ifdef ASSERT
+	assert(m_numberOfBytes>0);
+	#endif /* ASSERT */
+
+	m_memory=(uint8_t*)__Malloc(sizeof(uint8_t)*m_numberOfBytes,m_type,show);
+	m_bufferStates=(uint8_t*)__Malloc(m_chunks*sizeof(uint8_t),m_type,show);
+
+	for(int i=0;i<m_chunks;i++)
+		m_bufferStates[i]= BUFFER_STATE_AVAILABLE;
+
+	m_current=0;// the current head for allocation operations
+
+	m_show=show;
+
+	// in the beginning, all buffers are available
+	m_availableBuffers=m_chunks;
+
+	#if 0
+	cout<<"[RingAllocator] m_chunks: "<<m_chunks<<" m_max: "<<m_max<<endl;
+	#endif
+
+	#ifdef ASSERT
+	assert(size>0);
+	assert(chunks>0);
+
+	if(m_chunks==0)
+		cout<<"Error: chunks: "<<chunks<<" m_chunks: "<<m_chunks<<endl;
+
+	assert(m_chunks>0);
+	assert(m_max>0);
+	#endif /* ASSERT */
+}
+
+RingAllocator::RingAllocator(){}
+
+/*
+ * allocate a chunk of m_max bytes in constant time
+ */
+void*RingAllocator::allocate(int a){
+	#ifdef ASSERT
+	m_count++;
+	if(a>m_max){
+		cout<<"Request "<<a<<" but maximum is "<<m_max<<endl;
+	}
+	assert(a<=m_max);
+	#endif
+
+	int origin=m_current;
+
+	// first half of the circle
+	// from origin to N-1
+	while(m_bufferStates[m_current] == BUFFER_STATE_DIRTY
+	&& m_current < m_chunks){
+
+		m_current++;
+
+	}
+
+	// start from 0 if we completed.
+	// set i to 0
+	if(m_current==m_chunks){
+		m_current=0;
+	}
+
+	// from 0 to origin-1
+	while(m_bufferStates[m_current] == BUFFER_STATE_DIRTY
+	&& m_current < origin){
+
+		m_current++;
+	}
+
+	// if all buffers are dirty, we throw a runtime error
+	#ifdef ASSERT
+	if(m_current==origin && m_bufferStates[m_current]==BUFFER_STATE_DIRTY){
+		cout<<"Error: all buffers are dirty !, chunks: "<<m_chunks<<endl;
+		assert(m_current!=origin);
+	}
+	#endif
+
+	void*address=(void*)(m_memory+m_current*m_max);
+
+
+	m_current++;
+
+	// depending on the architecture
+	// branching (if) can be faster than integer division/modulo
+
+	if(m_current==m_chunks){
+		m_current=0;
+	}
+
+	return address;
+}
+
+void RingAllocator::salvageBuffer(void*buffer){
+	int bufferNumber=getBufferHandle(buffer);
+
+	m_bufferStates[bufferNumber]= BUFFER_STATE_AVAILABLE;
+
+	#ifdef CONFIG_RING_VERBOSE
+	cout<<"[RingAllocator::salvageBuffer] "<<bufferNumber<<" -> BUFFER_STATE_AVAILABLE"<<endl;
+	#endif
+
+	m_availableBuffers++;
+
+	#ifdef ASSERT
+	assert(m_availableBuffers>=1);
+	#endif
+
+}
+
+void RingAllocator::markBufferAsDirty(void*buffer){
+	int bufferNumber=getBufferHandle(buffer);
+
+	m_bufferStates[bufferNumber]= BUFFER_STATE_DIRTY;
+
+	#ifdef CONFIG_RING_VERBOSE
+	cout<<"[RingAllocator::markBufferAsDirty] "<<bufferNumber<<" -> BUFFER_STATE_DIRTY"<<endl;
+	#endif
+
+	#ifdef ASSERT
+	assert(m_availableBuffers>=1);
+	#endif
+
+	m_availableBuffers--;
+
+	#ifdef ASSERT
+	assert(m_availableBuffers>=0);
+	#endif
+}
+
+int RingAllocator::getBufferHandle(void*buffer){
+
+	void*origin=m_memory;
+
+	uint64_t originValue=(uint64_t)origin;
+	uint64_t bufferValue=(uint64_t)buffer;
+
+	uint64_t difference=bufferValue-originValue;
+
+	int index=difference/(m_max*sizeof(uint8_t));
+
+	return index;
+}
+
+int RingAllocator::getSize(){
+	return m_max;
+}
+
+void RingAllocator::clear(){
+	__Free(m_memory,m_type,m_show);
+	m_memory=NULL;
+}
+
+void RingAllocator::resetCount(){
+	m_count=0;
+}
+
+int RingAllocator::getCount(){
+	return m_count;
+}
+
+int RingAllocator::getNumberOfBuffers(){
+	return m_chunks;
+}
diff --git a/RayPlatform/memory/RingAllocator.h b/RayPlatform/memory/RingAllocator.h
new file mode 100644
index 0000000..9dee86c
--- /dev/null
+++ b/RayPlatform/memory/RingAllocator.h
@@ -0,0 +1,105 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _RingAllocator
+#define _RingAllocator
+
+#include<set>
+#include<stdint.h>
+#include <core/types.h> 
+using namespace std;
+
+/**
+ * This class is a ring buffer. No !, it is an allocator. Thus, referred to as a ring allocator.
+ *
+ * This is an allocator that can allocate up to <m_chunks> allocations of exactly <m_max> bytes.
+ * allocation and free are done both in constant time (yeah!)
+ * \author Sébastien Boisvert
+ */
+class RingAllocator{
+/** the number of call to allocate() since the last hard reset */
+	int m_count;
+
+/** the number of memory cells */
+	int m_chunks;
+
+/** the number of bytes, linear in the number of chunks/cells */
+	int m_numberOfBytes;
+
+/** the maximum size of a buffer */
+	int m_max;
+
+/** the number of available buffers */
+	int m_availableBuffers;
+
+/** the head */
+	int m_current;
+
+	bool m_show;
+/** memory block */
+
+	uint8_t*m_memory;
+
+	char m_type[100];
+	
+	uint8_t*m_bufferStates;
+
+
+public:
+	RingAllocator();
+	void constructor(int chunks,int size,const char*type,bool show);
+
+/** allocate memory */
+	void*allocate(int a);
+
+/**
+ * Gets the size of each buffer
+ */
+	int getSize();
+
+	void clear();
+	void resetCount();
+	int getCount();
+
+/**
+ * marks a buffer as available
+ */
+	void salvageBuffer(void*buffer);
+
+/**
+ * marks a buffer as used
+ */
+	void markBufferAsDirty(void*buffer);
+
+/**
+ * returns the number of buffers in the ring
+ */
+	int getNumberOfBuffers();
+
+/**
+ * get the handle for a buffer
+ */
+	int getBufferHandle(void*buffer);
+};
+
+
+#endif
+
diff --git a/RayPlatform/memory/allocator.cpp b/RayPlatform/memory/allocator.cpp
new file mode 100644
index 0000000..93f4dff
--- /dev/null
+++ b/RayPlatform/memory/allocator.cpp
@@ -0,0 +1,72 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <memory/allocator.h>
+#include <iostream>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <core/OperatingSystem.h>
+//#include <core/constants.h>
+using namespace std;
+
+/**
+ * wrapper around malloc
+ */
+void*__Malloc(int c,const char*description,bool show){
+	#ifdef ASSERT
+	if(c==0){
+		cout<<"Requested "<<c<<" bytes of type "<<description<<endl;
+	}
+	assert(c!=0);
+	assert(c>0);
+	#endif
+
+	void*a=NULL;
+	a=malloc(c);
+	if(a==NULL){
+		cout<<"Critical exception: The system is out of memory, returned NULL."<<endl;
+		cout<<"Requested "<<c<<" bytes of type "<<description<<endl;
+		exit(EXIT_NO_MORE_MEMORY);
+	}
+
+	assert(a!=NULL);
+
+	if(show){
+		printf("%s %i\t%s\t%i bytes, ret\t%p\t%s\n",__FILE__,__LINE__,__func__,c,a,description);
+		fflush(stdout);
+	}
+	return a;
+}
+
+/**
+ * wrapper around free
+ */
+void __Free(void*a,const char*description,bool show){
+	if(show){
+		printf("%s %i\t%s\t%p\t%s\n",__FILE__,__LINE__,__func__,a,description);
+		fflush(stdout);
+	}
+
+	free(a);
+}
+
+
diff --git a/RayPlatform/memory/allocator.h b/RayPlatform/memory/allocator.h
new file mode 100644
index 0000000..e421c00
--- /dev/null
+++ b/RayPlatform/memory/allocator.h
@@ -0,0 +1,31 @@
+/*
+Ray
+Copyright (C)  2010, 2011, 2012  Sébastien Boisvert
+
+http://DeNovoAssembler.SourceForge.Net/
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You have received a copy of the GNU Lesser General Public License
+along with this program (lgpl-3.0.txt).  
+see <http://www.gnu.org/licenses/>
+
+*/
+
+/**
+ * allocate c bytes of type mallocType
+ */
+void*__Malloc(int c,const char*description,bool show);
+
+/**
+ * free bytes of mallocType
+ */
+void __Free(void*a,const char*description,bool show);
+
diff --git a/RayPlatform/plugins/CorePlugin.cpp b/RayPlatform/plugins/CorePlugin.cpp
new file mode 100644
index 0000000..45d07a9
--- /dev/null
+++ b/RayPlatform/plugins/CorePlugin.cpp
@@ -0,0 +1,32 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <plugins/CorePlugin.h>
+
+// empty implementation
+void CorePlugin::registerPlugin(ComputeCore*computeCore){
+}
+
+void CorePlugin::resolveSymbols(ComputeCore*core){
+}
+
+CorePlugin::~CorePlugin(){
+}
diff --git a/RayPlatform/plugins/CorePlugin.h b/RayPlatform/plugins/CorePlugin.h
new file mode 100644
index 0000000..ee4d324
--- /dev/null
+++ b/RayPlatform/plugins/CorePlugin.h
@@ -0,0 +1,71 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _CorePlugin_h
+#define _CorePlugin_h
+
+#include <core/types.h>
+
+/** get the static name for the variable **/
+#define __GetPlugin(corePlugin) \
+	staticPlugin_ ## corePlugin
+
+/** get the method name in the plugin **/
+#define __GetMethod(handle) \
+	call_ ## handle
+
+/** get the function pointer name for the adapter **/
+#define __GetAdapter(corePlugin,handle) \
+	Adapter_ ## corePlugin ## _call_ ## handle 
+
+/* create the static core pluging thing. */
+#define __CreatePlugin( corePlugin ) \
+	static corePlugin * __GetPlugin( corePlugin ) ;
+
+#define __BindPlugin( corePlugin ) \
+	__GetPlugin( corePlugin ) = this;
+
+class ComputeCore;
+
+/** 
+ * In the Ray Platform, plugins are registered onto the
+ * core (ComputeCore).
+ * The only method of this interface is to register the plugin.
+ */
+class CorePlugin{
+
+protected:
+
+	PluginHandle m_plugin;
+
+public:
+
+/** register the plugin **/
+	virtual void registerPlugin(ComputeCore*computeCore);
+
+/** resolve the symbols **/
+	virtual void resolveSymbols(ComputeCore*core);
+
+	virtual ~CorePlugin();
+};
+
+#endif
+
diff --git a/RayPlatform/plugins/RegisteredPlugin.cpp b/RayPlatform/plugins/RegisteredPlugin.cpp
new file mode 100644
index 0000000..d137eff
--- /dev/null
+++ b/RayPlatform/plugins/RegisteredPlugin.cpp
@@ -0,0 +1,209 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <plugins/RegisteredPlugin.h>
+#include <core/slave_modes.h>
+#include <core/master_modes.h>
+#include <communication/mpi_tags.h>
+
+#include <iostream>
+using namespace std;
+
+RegisteredPlugin::RegisteredPlugin(){
+	m_name="No name available";
+	m_description="No description available";
+	m_authors="No authors available";
+	m_license="No license available";
+}
+
+void RegisteredPlugin::setPluginName(const char*name){
+	m_name=name;
+}
+
+void RegisteredPlugin::addAllocatedSlaveMode(SlaveMode slaveMode){
+	m_allocatedSlaveModes.insert(slaveMode);
+}
+
+void RegisteredPlugin::addAllocatedMasterMode(MasterMode masterMode){
+	m_allocatedMasterModes.insert(masterMode);
+}
+
+void RegisteredPlugin::addAllocatedMessageTag(MessageTag messageTag){
+	m_allocatedMessageTags.insert(messageTag);
+}
+
+void RegisteredPlugin::addRegisteredSlaveModeHandler(SlaveMode slaveMode){
+	m_registeredSlaveModeHandlers.insert(slaveMode);
+}
+
+void RegisteredPlugin::addRegisteredMasterModeHandler(MasterMode masterMode){
+	m_registeredMasterModeHandlers.insert(masterMode);
+}
+
+void RegisteredPlugin::addRegisteredMessageTagHandler(MessageTag messageTag){
+	m_registeredMessageTagHandlers.insert(messageTag);
+}
+
+void RegisteredPlugin::addRegisteredSlaveModeSymbol(SlaveMode slaveMode){
+	m_registeredSlaveModeSymbols.insert(slaveMode);
+}
+
+void RegisteredPlugin::addRegisteredMasterModeSymbol(MasterMode masterMode){
+	m_registeredMasterModeSymbols.insert(masterMode);
+}
+
+void RegisteredPlugin::addRegisteredMessageTagSymbol(MessageTag messageTag){
+	m_registeredMessageTagSymbols.insert(messageTag);
+}
+
+bool RegisteredPlugin::hasSlaveMode(SlaveMode mode){
+	return m_allocatedSlaveModes.count(mode)>0;
+}
+
+bool RegisteredPlugin::hasMasterMode(MasterMode mode){
+	return m_allocatedMasterModes.count(mode)>0;
+}
+
+bool RegisteredPlugin::hasMessageTag(MessageTag tag){
+	return m_allocatedMessageTags.count(tag)>0;
+}
+
+string RegisteredPlugin::getPluginName(){
+	return m_name;
+}
+
+void RegisteredPlugin::print(ostream*stream){
+
+	(*stream)<<"Name: "<<getPluginName()<<endl;
+	(*stream)<<"Description: "<<getPluginDescription()<<endl;
+	(*stream)<<"Authors: "<<getPluginAuthors()<<endl;
+	(*stream)<<"License: "<<getPluginLicense()<<endl;
+	(*stream)<<endl;
+	
+	(*stream)<<"Allocated handles"<<endl;
+	(*stream)<<endl;
+
+	(*stream)<<"-> Allocated MasterMode handles: "<<m_allocatedMasterModes.size()<<endl;
+	(*stream)<<"   -> with a registered symbol: "<<m_registeredMasterModeSymbols.size()<<endl;
+	(*stream)<<"   -> with a registered MasterModeHandler: "<<m_registeredMasterModeHandlers.size()<<endl;
+	(*stream)<<"   -> with a registered MasterMode-to-MessageTag switch: "<<m_registeredMasterModeToMessageTagSwitches.size()<<endl;
+	(*stream)<<"   -> with a registered next MasterMode: "<<m_registeredMasterModeNextMasterModes.size()<<endl;
+	(*stream)<<"   -> registered as first MasterMode: "<<m_registeredFirstMasterModes.size()<<endl;
+	(*stream)<<endl;
+
+	(*stream)<<"-> Allocated SlaveMode handles: "<<m_allocatedSlaveModes.size()<<endl;
+	(*stream)<<"   -> with a registered symbol: "<<m_registeredSlaveModeSymbols.size()<<endl;
+	(*stream)<<"   -> with a registered SlaveModeHandler: "<<m_registeredSlaveModeHandlers.size()<<endl;
+	(*stream)<<endl;
+
+	(*stream)<<"-> Allocated MessageTag handles: "<<m_allocatedMessageTags.size()<<endl;
+	(*stream)<<"   -> with a registered symbol: "<<m_registeredMessageTagSymbols.size()<<endl;
+	(*stream)<<"   -> with a registered MessageTagHandler: "<<m_registeredMessageTagHandlers.size()<<endl;
+	(*stream)<<"   -> with a registered MessageTag-to-SlaveMode switch: "<<m_registeredMessageTagToSlaveModeSwitches.size()<<endl;
+	(*stream)<<"   -> with a registered reply MessageTag: "<<m_registeredMessageTagReplyTags.size()<<endl;
+	(*stream)<<"   -> with a registered size: "<<m_registeredMessageTagSizes.size()<<endl;
+	(*stream)<<endl;
+
+	(*stream)<<"-> Allocated object handles: "<<m_allocatedObjects.size()<<endl;
+	(*stream)<<"   -> with a registered symbol: "<<m_registeredObjectSymbols.size()<<endl;
+	(*stream)<<endl;
+
+	(*stream)<<"Resolved symbols"<<endl;
+
+	(*stream)<<endl;
+	(*stream)<<"-> Resolved MasterMode symbols: "<<m_resolvedMasterModes.size()<<endl;
+	(*stream)<<"-> Resolved SlaveMode symbols: "<<m_resolvedSlaveModes.size()<<endl;
+	(*stream)<<"-> Resolved MessageTag symbols: "<<m_resolvedMessageTags.size()<<endl;
+	(*stream)<<"-> Resolved object symbols: "<<m_resolvedObjects.size()<<endl;
+	(*stream)<<endl;
+}
+
+void RegisteredPlugin::addResolvedMessageTag(MessageTag handle){
+	m_resolvedMessageTags.insert(handle);
+}
+
+void RegisteredPlugin::addResolvedSlaveMode(SlaveMode handle){
+	m_resolvedSlaveModes.insert(handle);
+}
+
+void RegisteredPlugin::addResolvedMasterMode(MasterMode handle){
+	m_resolvedMasterModes.insert(handle);
+}
+
+void RegisteredPlugin::setPluginDescription(const char*a){
+	m_description=a;
+}
+
+void RegisteredPlugin::setPluginAuthors(const char*a){
+	m_authors=a;
+}
+
+void RegisteredPlugin::setPluginLicense(const char*a){
+	m_license=a;
+}
+
+string RegisteredPlugin::getPluginDescription(){
+	return m_description;
+}
+
+string RegisteredPlugin::getPluginLicense(){
+	return m_license;
+}
+
+string RegisteredPlugin::getPluginAuthors(){
+	return m_authors;
+}
+
+void RegisteredPlugin::addRegisteredMasterModeToMessageTagSwitch(MasterMode mode){
+	m_registeredMasterModeToMessageTagSwitches.insert(mode);
+}
+
+void RegisteredPlugin::addRegisteredMessageTagToSlaveModeSwitch(SlaveMode mode){
+	m_registeredMessageTagToSlaveModeSwitches.insert(mode);
+}
+
+void RegisteredPlugin::addRegisteredMessageTagReplyMessageTag(MessageTag tag){
+	m_registeredMessageTagReplyMessageTags.insert(tag);
+}
+
+void RegisteredPlugin::addRegisteredMessageTagSize(MessageTag tag){
+	m_registeredMessageTagSizes.insert(tag);
+}
+
+void RegisteredPlugin::addRegisteredMasterModeNextMasterMode(MasterMode mode){
+	m_registeredMasterModeNextMasterModes.insert(mode);
+}
+
+void RegisteredPlugin::addRegisteredFirstMasterMode(MasterMode mode){
+	m_registeredFirstMasterModes.insert(mode);
+}
+
+void RegisteredPlugin::addAllocatedObject(int i){
+	m_allocatedObjects.insert(i);
+}
+
+void RegisteredPlugin::addRegisteredObjectSymbol(int i){
+	m_registeredObjectSymbols.insert(i);
+}
+
+void RegisteredPlugin::addResolvedObject(int i){
+	m_resolvedObjects.insert(i);
+}
diff --git a/RayPlatform/plugins/RegisteredPlugin.h b/RayPlatform/plugins/RegisteredPlugin.h
new file mode 100644
index 0000000..d108fdb
--- /dev/null
+++ b/RayPlatform/plugins/RegisteredPlugin.h
@@ -0,0 +1,113 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _RegisteredPlugin_h
+#define _RegisteredPlugin_h
+
+#include <core/types.h>
+#include <set>
+#include <string>
+#include <iostream>
+using namespace std;
+
+/**
+ * a registered plugin
+ */
+class RegisteredPlugin{
+
+	string m_name;
+	string m_description;
+	string m_authors;
+	string m_license;
+
+	set<MasterMode> m_resolvedMasterModes;
+	set<SlaveMode> m_resolvedSlaveModes;
+	set<MessageTag> m_resolvedMessageTags;
+
+	set<MasterMode> m_allocatedMasterModes;
+	set<MasterMode> m_registeredMasterModeSymbols;
+	set<MasterMode> m_registeredMasterModeHandlers;
+	set<MasterMode> m_registeredMasterModeToMessageTagSwitches;
+	set<MasterMode> m_registeredMasterModeNextMasterModes;
+	set<MasterMode> m_registeredFirstMasterModes;
+
+	set<SlaveMode> m_allocatedSlaveModes;
+	set<SlaveMode> m_registeredSlaveModeSymbols;
+	set<SlaveMode> m_registeredSlaveModeHandlers;
+
+	set<MessageTag> m_allocatedMessageTags;
+	set<MessageTag> m_registeredMessageTagSymbols;
+	set<MessageTag> m_registeredMessageTagHandlers;
+	set<MessageTag> m_registeredMessageTagReplyTags;
+	set<MessageTag> m_registeredMessageTagToSlaveModeSwitches;
+	set<MessageTag> m_registeredMessageTagReplyMessageTags;
+	set<MessageTag> m_registeredMessageTagSizes;
+
+	set<int> m_allocatedObjects;
+	set<int> m_registeredObjectSymbols;
+	set<int> m_resolvedObjects;
+public:
+
+	RegisteredPlugin();
+
+	void setPluginName(const char*name);
+	void setPluginDescription(const char*text);
+	void setPluginAuthors(const char*text);
+	void setPluginLicense(const char*text);
+
+	string getPluginName();
+	string getPluginDescription();
+	string getPluginLicense();
+	string getPluginAuthors();
+
+	void addRegisteredMasterModeSymbol(MasterMode masterMode);
+	void addAllocatedMasterMode(MasterMode masterMode);
+	void addRegisteredMasterModeHandler(MasterMode masterMode);
+	void addResolvedMasterMode(MasterMode masterMode);
+	void addRegisteredMasterModeToMessageTagSwitch(MasterMode mode);
+	void addRegisteredMasterModeNextMasterMode(MasterMode mode);
+	void addRegisteredFirstMasterMode(MasterMode mode);
+
+	void addAllocatedSlaveMode(SlaveMode slaveMode);
+	void addRegisteredSlaveModeHandler(SlaveMode slaveMode);
+	void addRegisteredSlaveModeSymbol(SlaveMode slaveMode);
+	void addResolvedSlaveMode(SlaveMode handle);
+
+	void addAllocatedMessageTag(MessageTag messageTag);
+	void addRegisteredMessageTagHandler(MessageTag messageTag);
+	void addRegisteredMessageTagSymbol(MessageTag messageTag);
+	void addResolvedMessageTag(MessageTag handle);
+	void addRegisteredMessageTagToSlaveModeSwitch(MessageTag handle);
+	void addRegisteredMessageTagReplyMessageTag(MessageTag tag);
+	void addRegisteredMessageTagSize(MessageTag tag);
+
+	void addAllocatedObject(int i);
+	void addRegisteredObjectSymbol(int i);
+	void addResolvedObject(int i);
+
+	bool hasSlaveMode(SlaveMode mode);
+	bool hasMasterMode(MasterMode mode);
+	bool hasMessageTag(MessageTag tag);
+
+	void print(ostream*stream);
+};
+
+#endif
diff --git a/RayPlatform/profiling/Derivative.cpp b/RayPlatform/profiling/Derivative.cpp
new file mode 100644
index 0000000..877c06c
--- /dev/null
+++ b/RayPlatform/profiling/Derivative.cpp
@@ -0,0 +1,95 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <profiling/Derivative.h>
+#include <core/statistics.h>
+#include <core/slave_modes.h>
+#include <core/OperatingSystem.h>
+
+#include <iostream>
+using namespace std;
+
+Derivative::Derivative(){
+}
+
+void Derivative::addX(int x){
+	m_xValues.push_back(x);
+	m_timeValues.push_back(getMicroseconds());
+}
+
+int Derivative::getLastSlope(){
+	if(m_xValues.size()<2)
+		return 0;
+
+	int n=m_xValues.size();
+
+	int slope=(int)(1000*1000*(m_xValues[n-1]-m_xValues[n-2]+0.0)/(m_timeValues[n-1]-m_timeValues[n-2]+0.0));
+
+	if(slope<0)
+		return 0;
+
+	return slope;
+}
+
+void Derivative::printStatus(const char*mode,int modeIdentifier){
+	if(m_xValues.size()<2)
+		return;
+
+	int value=getLastSlope();
+
+	cout<<"Speed "<<mode<<" "<<value<<" units/second"<<endl;
+
+	m_data[modeIdentifier].push_back(value);
+}
+
+void Derivative::clear(){
+	m_xValues.clear();
+	m_timeValues.clear();
+}
+
+void Derivative::printEstimatedTime(int total){
+	int n=m_xValues.size();
+
+	if(m_xValues.size()<2)
+		return;
+
+	int last=m_xValues[n-1];
+
+	int remaining=total-last;
+
+	double slope=getLastSlope();
+
+	int remainingSeconds=(int)(remaining/slope);
+
+	cout<<"Estimated remaining time for this step: ";
+
+	printTheSeconds(remainingSeconds,&cout);
+
+	cout<<endl;
+}
+
+void Derivative::writeFile(ostream*f){
+	for(map<int,vector<int> >::iterator i=m_data.begin();
+		i!=m_data.end();i++){
+		int average=(int)getAverage(&(i->second));
+		*f<<"AverageSpeed "<<SLAVE_MODES[i->first]<<"	"<<average<<" units/second"<<endl;
+	}
+}
diff --git a/RayPlatform/profiling/Derivative.h b/RayPlatform/profiling/Derivative.h
new file mode 100644
index 0000000..20f5361
--- /dev/null
+++ b/RayPlatform/profiling/Derivative.h
@@ -0,0 +1,54 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _Derivative_h
+#define _Derivative_h
+
+#include <vector>
+#include <fstream>
+#include <core/OperatingSystem.h>
+#include <map>
+#include <stdint.h>
+using namespace std;
+
+/**
+ * this class stores the progress of a computation task.
+ * When asked, it prints the estimated remaining time.
+ */
+class Derivative{
+	map<int,vector<int> > m_data;
+
+	vector<uint64_t> m_timeValues;
+	vector<int> m_xValues;
+
+public:
+	Derivative();
+	void addX(int x);
+	int getLastSlope();
+	void printStatus(const char*mode,int modeIdentifier);
+	void printEstimatedTime(int n);
+	void clear();
+
+	void writeFile(ostream*f);
+};
+
+#endif
+
diff --git a/RayPlatform/profiling/Profiler.cpp b/RayPlatform/profiling/Profiler.cpp
new file mode 100644
index 0000000..9d3bc89
--- /dev/null
+++ b/RayPlatform/profiling/Profiler.cpp
@@ -0,0 +1,152 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <core/OperatingSystem.h>
+#include <profiling/Profiler.h>
+#include <core/slave_modes.h>
+#include <assert.h>
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+void Profiler::constructor(bool isEnabled){
+	m_enabled = isEnabled;
+	m_threshold = 64;
+}
+
+void Profiler::resetStack(){
+	m_timePoints.clear();
+	m_functions.clear();
+	m_files.clear();
+	m_lines.clear();
+}
+
+void Profiler::collect(const char*function,const char*file,int line){
+	m_timePoints.push_back(getThreadMicroseconds());
+	m_functions.push_back(function);
+	m_files.push_back(file);
+	m_lines.push_back(line);
+}
+
+void Profiler::printStack(){
+	if(m_timePoints.size() == 0){
+		cout<<"The stack is empty."<<endl;
+		return;
+	}
+
+	cout<<"Number of calls in the stack: "<<m_timePoints.size()<<endl;
+	uint64_t start=0;
+	uint64_t total=0;
+	if(m_timePoints.size() > 0){
+		start=m_timePoints[0];
+
+		total=m_timePoints[m_timePoints.size()-1];
+
+		if(m_timePoints.size() > 1)
+			total -= start;
+	}
+
+	for(int i=0;i<(int)m_timePoints.size();i++){
+		int last=i-1;
+		if(last<0)
+			last=0;
+		uint64_t current=m_timePoints[i];
+		uint64_t lastPoint=m_timePoints[last];
+		//uint64_t diffWithStart=current-start;
+		uint64_t diffWithLast=current-lastPoint;
+
+		double ratio=0;
+
+		if(total > 0)
+			ratio=100.00*diffWithLast/total;
+
+		cout<<i<<"	"<<current<<" microseconds	+ "<<diffWithLast<<" from previous ("<<setprecision(2)<<fixed<< ratio<<"%)";
+		//cout<<"	+"<<diffWithStart<<" from first";
+		cout<<"	in "<<m_functions[i]<<" inside "<<m_files[i]<<" at line "<<m_lines[i]<<endl;
+	}
+	cout<<"End of stack"<<endl;
+}
+
+bool Profiler::isEnabled(){
+	return m_enabled;
+}
+
+int Profiler::getThreshold(){
+	return m_threshold;
+}
+
+void Profiler::addGranularity(int mode,int microseconds){
+	m_granularityValues[microseconds] ++ ;
+	m_observedGranularities[mode][microseconds] ++;
+}
+
+void Profiler::printGranularities(int rank){
+	cout<<"Rank "<<rank<<" granularity of processData calls"<<endl;
+	for(map<int,int>::iterator i = m_granularityValues.begin();i!= m_granularityValues.end();i++){
+		int microSeconds=i->first;
+		int count=i->second;
+		cout<<" "<<microSeconds<<" "<<count<<endl;
+	}
+	cout<<"Rank "<<rank<<" END of granularity of processData calls"<<endl;
+	m_granularityValues.clear();
+}
+
+/* report a summary of granularities */
+void Profiler::printAllGranularities(){
+	cout<<"Summary of granularities"<<endl;
+
+	for(map<int,map<int,uint64_t> >::iterator i=m_observedGranularities.begin();
+		i!=m_observedGranularities.end();i++){
+		cout<<"SlaveMode= "<<SLAVE_MODES[i->first]<<endl;
+		cout<<"Sampled granularities:"<<endl;
+
+		uint64_t total=0;
+		for(map<int,uint64_t>::iterator j=i->second.begin();j!=i->second.end();j++){
+			total += j->second;
+		}
+
+		uint64_t cumulativeValue=0;
+
+		for(map<int,uint64_t>::iterator j=i->second.begin();j!=i->second.end();j++){
+			int granularity=j->first;
+			uint64_t count=j->second;
+			cumulativeValue += count;
+			double ratio=100.0*count;
+			double ratio2=100.0*cumulativeValue;
+
+			if(total > 0){
+				ratio /= total;
+				ratio2 /= total;
+			}
+
+			cout<<"	"<<granularity<<"	"<<count<<"	"<<setprecision(2)<<fixed<<ratio<<"%";
+			cout<<"	CumulativeRatio: "<<setprecision(2)<<fixed<<ratio2<<"%";
+			cout<<endl;
+		}
+		cout<<"/End of sampled granularities"<<endl;
+		cout<<endl;
+	}
+
+}
+
+void Profiler::clearGranularities(){
+	m_observedGranularities.clear();
+}
diff --git a/RayPlatform/profiling/Profiler.h b/RayPlatform/profiling/Profiler.h
new file mode 100644
index 0000000..ed4dd9f
--- /dev/null
+++ b/RayPlatform/profiling/Profiler.h
@@ -0,0 +1,99 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _Profiler_H
+#define _Profiler_H
+
+#include <vector>
+#include <stdint.h>
+#include <string>
+#include <map>
+using namespace std;
+
+/**
+ * when enabled, this profiler collects data and 
+ * reports some things.
+ * To collect something somewhere, add the line
+ *
+ * MACRO_COLLECT_PROFILING_INFORMATION();
+ *
+ * Also, the code (your application and RayPlatform) 
+ * must be compiled with -D CONFIG_PROFILER_COLLECT
+ *
+ * To compile the profiling code.
+ */
+class Profiler{
+	vector<uint64_t> m_timePoints;
+	vector<string> m_functions;
+	vector<string> m_files;
+	vector<int> m_lines;
+
+	bool m_enabled;
+
+	int m_threshold;
+
+	map<int,int> m_granularityValues;
+
+	/* store the granularities for each slave mode */
+	map<int,map<int,uint64_t> > m_observedGranularities;
+
+public:
+	void constructor(bool enabled);
+	void resetStack();
+	void printStack();
+
+/** collect information */
+	void collect(const char*function,const char*file,int line);
+
+	bool isEnabled();
+	int getThreshold();
+
+/** add information about a task */
+	void addGranularity(int mode,int microseconds);
+
+	void printGranularities(int rank);
+	void printAllGranularities();
+
+	void clearGranularities();
+};
+
+/* if CONFIG_PROFILER_COLLECT is defined, MACRO_COLLECT_PROFILING_INFORMATION() will collect profiling information
+ * if -run-profiler was provided
+ * otherwise, nothing is collected even if -run-profiler is provided 
+ * the default is to define CONFIG_PROFILER_COLLECT 
+ * and enable the profiler with -run-profiler (default is to not enable it)
+ *
+ * m_profiler must be a boolean in the context where the MACRO_COLLECT_PROFILING_INFORMATION is written.
+ * and m_profiler must be the instance of the Profiler class and it must be a pointer to it.
+ * */
+
+#ifdef CONFIG_PROFILER_COLLECT
+
+#define MACRO_COLLECT_PROFILING_INFORMATION() \
+	if(m_profiler != NULL && m_profiler->isEnabled()) \
+		m_profiler->collect(__func__,__FILE__,__LINE__);
+
+#else
+#define MACRO_COLLECT_PROFILING_INFORMATION()
+#endif
+
+
+#endif
diff --git a/RayPlatform/profiling/TickLogger.cpp b/RayPlatform/profiling/TickLogger.cpp
new file mode 100644
index 0000000..f8fcac3
--- /dev/null
+++ b/RayPlatform/profiling/TickLogger.cpp
@@ -0,0 +1,299 @@
+/*
+ 	Ray
+    Copyright (C) 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#include <profiling/TickLogger.h>
+#include <assert.h>
+#include <iostream>
+#include <time.h>
+#include <core/OperatingSystem.h>
+using namespace std;
+
+//#define CONFIG_DISPLAY_TICKS
+#define CONFIG_TICK_STEPPING 1000000
+
+void TickLogger::logSlaveTick(SlaveMode i){
+	#ifdef ASSERT
+	assert(i!=INVALID_HANDLE);
+	#endif
+
+	// this case occurs once during the first call
+	if(m_lastSlaveMode==INVALID_HANDLE){
+		// start the new entry
+		m_lastSlaveMode=i;
+		m_slaveCount=0;
+		m_slaveStarts.push_back(getTheTime());
+
+	// this is the same as the last one
+	}else if(i==m_lastSlaveMode){
+	
+		// nothing to do
+
+	// this is a new slave mode
+	}else{
+		// add the last entry
+		m_slaveModes.push_back(m_lastSlaveMode);
+		m_slaveCounts.push_back(m_slaveCount);
+
+		uint64_t stamp=getTheTime();
+		m_slaveEnds.push_back(stamp);
+		m_receivedMessageCounts.push_back(m_receivedMessageCount);
+		m_receivedMessageCount=0;
+		m_sentMessageCounts.push_back(m_sentMessageCount);
+		m_sentMessageCount=0;
+
+		// start the new entry
+		m_lastSlaveMode=i;
+		m_slaveCount=0;
+		m_slaveStarts.push_back(stamp);
+	}
+
+	// increment the ticks
+	m_slaveCount++;
+
+	#ifdef CONFIG_DISPLAY_TICKS
+	if(m_slaveCount% CONFIG_TICK_STEPPING == 0)
+		cout<<"[TickLogger::addSlaveTick] "<<SLAVE_MODES[i]<<" "<<m_slaveCount<<endl;
+	#endif
+}
+
+void TickLogger::logMasterTick(MasterMode i){
+	#ifdef ASSERT
+	assert(i!=INVALID_HANDLE);
+	#endif
+
+	// this case occurs once during the first call
+	if(m_lastMasterMode==INVALID_HANDLE){
+		// start the new entry
+		m_lastMasterMode=i;
+		m_masterCount=0;
+		m_masterStarts.push_back(getTheTime());
+
+	// this is the same as the last one
+	}else if(i==m_lastMasterMode){
+	
+		// Nothing to do
+
+	// this is a new slave mode
+	}else{
+
+		uint64_t stamp=getTheTime();
+
+		// add the last entry
+		m_masterModes.push_back(m_lastMasterMode);
+		m_masterCounts.push_back(m_masterCount);
+		m_masterEnds.push_back(stamp);
+
+		// start the new entry
+		m_lastMasterMode=i;
+		m_masterCount=0;
+		m_masterStarts.push_back(stamp);
+	}
+
+	m_masterCount++;
+
+	#ifdef CONFIG_DISPLAY_TICKS
+	if(m_masterCount% CONFIG_TICK_STEPPING == 0)
+		cout<<"[TickLogger::addMasterTick] "<<MASTER_MODES[i]<<" "<<m_masterCount<<endl;
+	#endif
+
+}
+
+void TickLogger::printSlaveTicks(ofstream*file){
+	// add the last entry
+	m_slaveModes.push_back(m_lastSlaveMode);
+	m_slaveCounts.push_back(m_slaveCount);
+	m_slaveEnds.push_back(getTheTime());
+	m_receivedMessageCounts.push_back(m_receivedMessageCount);
+	m_receivedMessageCount=0;
+	m_sentMessageCounts.push_back(m_sentMessageCount);
+	m_sentMessageCount=0;
+
+	// reset the entry
+	m_lastSlaveMode=INVALID_HANDLE;
+	m_slaveCount=0;
+
+	// print stuff
+	
+	#ifdef ASSERT
+	assert(m_slaveModes.size()==m_slaveCounts.size());
+	assert(m_slaveModes.size()==m_slaveStarts.size());
+	assert(m_slaveModes.size()==m_slaveEnds.size());
+	assert(m_slaveModes.size()==m_receivedMessageCounts.size());
+	assert(m_slaveModes.size()==m_sentMessageCounts.size());
+	#endif
+
+	uint64_t total=0;
+
+	for(int i=0;i<(int)m_slaveModes.size();i++){
+		total+=m_slaveCounts[i];
+	}
+
+	bool firstSet=false;
+	uint64_t firstTime=0;
+
+	(*file)<<"Index	Slave mode	Start time in milliseconds	End time in milliseconds	Duration in milliseconds	Number of ticks	Average granularity in nanoseconds	Received messages	Average number of received messages per second	Sent messages	Average number of sent messages per second"<<endl;
+	for(int i=0;i<(int)m_slaveModes.size();i++){
+		uint64_t startTime=m_slaveStarts[i];
+		uint64_t endTime=m_slaveEnds[i];
+
+		if(!firstSet){
+			firstSet=true;
+			firstTime=startTime;
+		}
+
+		int realStart=startTime-firstTime;
+		int realEnd=endTime-firstTime;
+		int delta=realEnd-realStart;
+
+		double ratio=m_slaveCounts[i];
+		if(total!=0)
+			ratio/=total;
+
+		uint64_t ticks=m_slaveCounts[i];
+
+		uint64_t granularity=delta;
+		granularity*=1000*1000;
+
+		#ifdef ASSERT
+		assert(ticks!=0);
+		#endif
+
+		granularity/=ticks;
+
+		uint64_t receptionSpeed=m_receivedMessageCounts[i];
+
+		if(delta!=0){
+			receptionSpeed*=1000;
+			receptionSpeed/=delta;
+		}
+
+		uint64_t sendingSpeed=m_sentMessageCounts[i];
+
+		if(delta!=0){
+			sendingSpeed*=1000;
+			sendingSpeed/=delta;
+		}
+
+		(*file)<<i<<"	"<<SLAVE_MODES[m_slaveModes[i]];
+		(*file)<<"	"<<realStart<<"	"<<realEnd<<"	"<<delta;
+		(*file)<<"	"<<ticks;
+		(*file)<<"	"<<granularity;
+		//<<"	"<<ratio<<endl;
+		(*file)<<"	"<<m_receivedMessageCounts[i]<<"	";
+		(*file)<<receptionSpeed<<"	";
+		(*file)<<m_sentMessageCounts[i];
+		(*file)<<"	"<<sendingSpeed;
+		(*file)<<endl;
+	}
+
+	m_slaveModes.clear();
+	m_slaveCounts.clear();
+	m_slaveStarts.clear();
+	m_slaveEnds.clear();
+}
+
+void TickLogger::printMasterTicks(ofstream*file){
+
+	// add the last entry
+	m_masterModes.push_back(m_lastMasterMode);
+	m_masterCounts.push_back(m_masterCount);
+	m_masterEnds.push_back(getTheTime());
+
+	// reset the entry
+	m_lastMasterMode=INVALID_HANDLE;
+	m_masterCount=0;
+
+	// print stuff
+	
+	#ifdef ASSERT
+	assert(m_masterModes.size()==m_masterCounts.size());
+	assert(m_masterModes.size()==m_masterStarts.size());
+	assert(m_masterModes.size()==m_masterEnds.size());
+	#endif
+	
+	(*file)<<"Index	Master mode	Start time in milliseconds	End time in milliseconds	Duration in milliseconds	Number of ticks	Average granularity in nanoseconds"<<endl;
+
+	uint64_t total=0;
+
+	for(int i=0;i<(int)m_masterModes.size();i++){
+		total+=m_masterCounts[i];
+	}
+
+	bool firstSet=false;
+	uint64_t firstTime=0;
+
+	for(int i=0;i<(int)m_masterModes.size();i++){
+
+		uint64_t startTime=m_masterStarts[i];
+		uint64_t endTime=m_masterEnds[i];
+		
+		if(!firstSet){
+			firstSet=true;
+			firstTime=startTime;
+		}
+
+		int realStart=startTime-firstTime;
+		int realEnd=endTime-firstTime;
+		int delta=endTime-startTime;
+		
+		double ratio=m_masterCounts[i];
+		if(total!=0)
+			ratio/=total;
+
+		uint64_t ticks=m_masterCounts[i];
+
+		uint64_t granularity=delta;
+		granularity*=1000*1000;
+
+		#ifdef ASSERT
+		assert(ticks!=0);
+		#endif
+
+		granularity/=ticks;
+
+		(*file)<<i<<"	"<<MASTER_MODES[m_masterModes[i]];
+		(*file)<<"	"<<realStart<<"	"<<realEnd<<"	";
+		(*file)<<delta<<"	"<<ticks<<"	"<<granularity<<endl;
+	}
+
+	m_masterModes.clear();
+	m_masterCounts.clear();
+	m_masterStarts.clear();
+	m_masterEnds.clear();
+}
+
+TickLogger::TickLogger(){
+	m_lastSlaveMode=INVALID_HANDLE;
+	m_lastMasterMode=INVALID_HANDLE;
+	m_slaveCount=0;
+	m_masterCount=0;
+}
+
+void TickLogger::logReceivedMessage(MessageTag i){
+	m_receivedMessageCount++;
+}
+
+void TickLogger::logSendMessage(MessageTag i){
+	m_sentMessageCount++;
+}
+
+uint64_t TickLogger::getTheTime(){
+	return getMilliSeconds();
+}
diff --git a/RayPlatform/profiling/TickLogger.h b/RayPlatform/profiling/TickLogger.h
new file mode 100644
index 0000000..b5bcd4f
--- /dev/null
+++ b/RayPlatform/profiling/TickLogger.h
@@ -0,0 +1,82 @@
+/*
+ 	Ray
+    Copyright (C) 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _TickLogger_h
+#define _TickLogger_h
+
+#include <core/master_modes.h>
+#include <core/slave_modes.h>
+
+#include <time.h>
+#include <fstream>
+#include <stdint.h>
+#include <vector>
+using namespace std;
+
+/** this class writes these files:
+ *
+ * Scheduling/Agenda.txt
+ * Scheduling/SlaveSwitches.txt
+ * Scheduling/MasterSwitches.txt
+ * Scheduling/SlaveModes.txt
+ * Scheduling/MasterModes.txt
+ *
+ * Scheduling/0.MasterTicks.txt
+ * Scheduling/0.SlaveTicks.txt
+ *
+ * ...
+ *
+ * To do so, it counts the ticks
+ */
+class TickLogger{
+	vector<uint64_t> m_slaveCounts;
+	vector<SlaveMode> m_slaveModes;
+	vector<uint64_t> m_slaveStarts;
+	vector<uint64_t> m_slaveEnds;
+	vector<uint64_t> m_receivedMessageCounts;
+	vector<uint64_t> m_sentMessageCounts;
+
+	SlaveMode m_lastSlaveMode;
+	uint64_t m_slaveCount;
+	uint64_t m_receivedMessageCount;
+	uint64_t m_sentMessageCount;
+
+	vector<uint64_t> m_masterCounts;
+	vector<MasterMode> m_masterModes;
+	vector<uint64_t> m_masterStarts;
+	vector<uint64_t> m_masterEnds;
+	MasterMode m_lastMasterMode;
+	uint64_t m_masterCount;
+
+	uint64_t getTheTime();
+public:
+
+	TickLogger();
+
+	void logSlaveTick(SlaveMode i);
+	void logMasterTick(MasterMode i);
+	void logReceivedMessage(MessageTag i);
+	void logSendMessage(MessageTag i);
+
+	void printSlaveTicks(ofstream*file);
+	void printMasterTicks(ofstream*file);
+};
+
+#endif
diff --git a/RayPlatform/profiling/TimePrinter.cpp b/RayPlatform/profiling/TimePrinter.cpp
new file mode 100644
index 0000000..b9fa14b
--- /dev/null
+++ b/RayPlatform/profiling/TimePrinter.cpp
@@ -0,0 +1,127 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <profiling/TimePrinter.h>
+#include <core/OperatingSystem.h>
+
+#include <stdio.h>
+#include <iostream>
+#include <sstream>
+using namespace std;
+
+void TimePrinter::printElapsedTime(string description){
+
+	m_endingTime=time(NULL);
+	int differenceWithLast=m_endingTime-m_lastTime;
+	m_lastTime=m_endingTime;
+	struct tm * timeinfo;
+	timeinfo=localtime(&m_endingTime);
+
+	m_descriptions.push_back(description);
+	m_durations.push_back(differenceWithLast);
+
+	printElapsedTimeInStream(&cout,description,timeinfo,differenceWithLast);
+
+	if(m_fileSet){
+		printElapsedTimeInStream(&m_file,description,timeinfo,differenceWithLast);
+	}
+}
+
+void TimePrinter::printElapsedTimeInStream(ostream*stream,string description,struct tm*timeinfo,
+int differenceWithLast){
+	(*stream)<<endl;
+	(*stream)<<"***"<<endl;
+	(*stream)<<"Step: "<<description<<endl;
+	(*stream)<<"Date: "<<asctime(timeinfo);
+	(*stream)<<"Elapsed time: ";
+	printDifference(differenceWithLast,stream);
+	int totalSeconds=m_endingTime-m_startingTime;
+	(*stream)<<endl;
+	(*stream)<<"Since beginning: ";
+	printDifference(totalSeconds,stream);
+	(*stream)<<endl;
+	(*stream)<<"***"<<endl;
+	(*stream)<<endl;
+	fflush(stdout);
+}
+
+void TimePrinter::printDifferenceFromStart(int rank){
+	time_t endingTime=time(NULL);
+	if(endingTime==m_last){
+		return;
+	}
+	if((endingTime-m_startingTime)%3600!=0){
+		return;
+	}
+	m_last=endingTime;
+	int differenceWithLast=endingTime-m_startingTime;
+	cout<<"Rank "<<rank<<": I am still running... ";
+	printDifference(differenceWithLast,&cout);
+	cout<<endl;
+}
+
+void TimePrinter::constructor(){
+	m_startingTime=m_lastTime=m_endingTime=time(NULL);
+	m_descriptions.clear();
+	m_durations.clear();
+
+	m_fileSet=false;
+}
+
+void TimePrinter::setFile(string prefix){
+	ostringstream fileName;
+	fileName<<prefix<<"ElapsedTime.txt";
+
+	m_file.open(fileName.str().c_str(),ios_base::out);
+
+	m_fileSet=true;
+}
+
+void TimePrinter::printDifference(int difference,ostream*stream){
+	printTheSeconds(difference,stream);
+}
+
+void TimePrinter::printDurations(){
+
+	m_endingTime=time(NULL);
+	struct tm * timeinfo;
+	timeinfo=localtime(&m_endingTime);
+	m_descriptions.push_back("Total");
+	m_durations.push_back(m_endingTime-m_startingTime);
+
+	printDurationsInStream(&cout,timeinfo);
+
+	if(m_fileSet){
+		printDurationsInStream(&m_file,timeinfo);
+		m_file.close();
+	}
+}
+
+void TimePrinter::printDurationsInStream(ostream*stream,struct tm*timeinfo){
+	(*stream)<<"\nElapsed time for each step, "<<asctime(timeinfo)<<endl;
+	for(int i=0;i<(int)m_descriptions.size();i++){
+		string text=m_descriptions[i];
+		int seconds=m_durations[i];
+		(*stream)<<" "<<text<<": ";
+		printDifference(seconds,stream);
+		(*stream)<<endl;
+	}
+}
diff --git a/RayPlatform/profiling/TimePrinter.h b/RayPlatform/profiling/TimePrinter.h
new file mode 100644
index 0000000..66371e4
--- /dev/null
+++ b/RayPlatform/profiling/TimePrinter.h
@@ -0,0 +1,61 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _TimePrinter
+#define _TimePrinter
+
+
+// TODO: move this class in the core
+#include<time.h>
+#include<vector>
+#include <fstream>
+#include<string>
+using namespace std;
+
+/**
+ * Prints the current local time.
+ * Also, prints the elapsed time since the beginning.
+ * \author Sébastien Boisvert
+ */
+class TimePrinter{
+	ofstream m_file;
+	bool m_fileSet;
+	time_t m_last;
+	time_t m_startingTime;
+	time_t m_lastTime;
+	time_t m_endingTime;
+	vector<string> m_descriptions;
+	vector<int> m_durations;
+
+	void printDifference(int s,ostream*stream);
+
+	void printDurationsInStream(ostream*stream,struct tm*t);
+	void printElapsedTimeInStream(ostream*stream, string description,struct tm*timeinfo,
+int differenceWithLast);
+public:
+	void printElapsedTime(string description);
+	void setFile(string prefix);
+	void constructor();
+	void printDurations();
+	void printDifferenceFromStart(int rank);
+};
+
+#endif
diff --git a/RayPlatform/routing/ConnectionGraph.cpp b/RayPlatform/routing/ConnectionGraph.cpp
new file mode 100644
index 0000000..1b154bb
--- /dev/null
+++ b/RayPlatform/routing/ConnectionGraph.cpp
@@ -0,0 +1,323 @@
+/*
+ 	RayPlatform
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <routing/ConnectionGraph.h>
+
+enum {
+__COMPLETE,
+__GROUP,
+__RANDOM,
+__DEBRUIJN,
+__KAUTZ,
+__EXPERIMENTAL,
+__HYPERCUBE
+};
+
+/**
+ * Print a route
+ */
+void ConnectionGraph::printRoute(Rank source,Rank destination){
+	cout<<"[printRoute] Source: "<<source<<"	Destination: "<<destination<<"	";
+
+	vector<Rank> route;
+	m_implementation->getRoute(source,destination,&route);
+
+	cout<<"Size: "<<route.size()<<"	Route: ";
+
+	for(int i=0;i<(int)route.size();i++){
+		if(i!=0)
+			cout<<" ";
+		cout<<route[i];
+	}
+	cout<<"	Hops: "<<route.size()-1<<endl;
+}
+
+
+/**
+ * a rank can only speak to things listed in connections
+ */
+bool ConnectionGraph::isConnected(Rank source,Rank destination){
+	// TODO: replace by a switch case to avoid virtual calls
+	return m_implementation->isConnected(source,destination);
+}
+
+/**
+ * Write files.
+ */
+void ConnectionGraph::writeFiles(string prefix){
+	// dump the connections in a file
+	ostringstream file;
+	file<<prefix<<"Connections.txt";
+	ofstream f(file.str().c_str());
+
+	f<<"#Rank	Count	Connections"<<endl;
+
+	for(Rank rank=0;rank<m_size;rank++){
+		vector<Rank> connections;
+		m_implementation->getOutcomingConnections(rank,&connections);
+
+		f<<rank<<"	"<<connections.size()<<"	";
+
+		for(vector<Rank>::iterator i=connections.begin();
+			i!=connections.end();i++){
+			if(i!=connections.begin())
+				f<<" ";
+			f<<*i;
+		}
+		f<<endl;
+	}
+
+	f.close();
+
+	// dump the routes in a file
+	ostringstream file2;
+	file2<<prefix<<"Routes.txt";
+	ofstream f2(file2.str().c_str());
+	
+	if(m_typeCode==__HYPERCUBE){
+		f2<<"Routes are dynamically determined with real-time load-balancing."<<endl;
+	}else{
+		f2<<"#Source	Destination	Hops	Route"<<endl;
+
+		for(Rank rank=0;rank<m_size;rank++){
+			for(Rank i=0;i<m_size;i++){
+				vector<Rank> route;
+				m_implementation->getRoute(rank,i,&route);
+				f2<<rank<<"	"<<i<<"	"<<route.size()-1<<"	";
+	
+				for(int i=0;i<(int)route.size();i++){
+					if(i!=0)
+						f2<<" ";
+					f2<<route[i];
+				}
+	
+				f2<<endl;
+			}
+		}
+	}
+
+	f2.close();
+
+	// write relay events
+	ostringstream file3;
+	file3<<prefix<<"RelayEvents.txt";
+	ofstream f3(file3.str().c_str());
+	f3<<"#Source	RelayEvents"<<endl;
+
+	vector<int> relayEvents;
+
+	for(Rank rank=0;rank<m_size;rank++){
+		int relays=m_implementation->getRelays(rank);
+		f3<<rank<<"	"<<relays<<endl;
+		relayEvents.push_back(relays);
+	}
+
+	f3.close();
+
+	// dump the routes in a file
+	ostringstream file4;
+	file4<<prefix<<"Summary.txt";
+	ofstream f4(file4.str().c_str());
+
+	int numberOfVertices=m_size;
+
+	int numberOfEdges=0;
+
+	vector<int> connectivities;
+
+	for(Rank i=0;i<m_size;i++){
+		vector<Rank> connections;
+
+		m_implementation->getOutcomingConnections(i,&connections);
+
+		connectivities.push_back(connections.size());
+		numberOfEdges+=connections.size();
+
+	}
+
+	f4<<"Type: "<<m_type<<endl;
+	f4<<endl;
+
+	f4<<"NumberOfVertices: "<<numberOfVertices<<endl;
+	f4<<"NumberOfArcs: "<<numberOfEdges<<endl;
+	f4<<"NumberOfArcsInCompleteGraph: "<<numberOfVertices*(numberOfVertices-1)<<endl;
+	f4<<endl;
+	f4<<"NumberOfOutcomingArcsPerVertex"<<endl;
+	f4<<"   Frequencies:"<<endl;
+
+	map<int,int> connectionFrequencies;
+	for(Rank i=0;i<m_size;i++){
+		vector<Rank> connections;
+		m_implementation->getOutcomingConnections(i,&connections);
+		connectionFrequencies[connections.size()]++;
+	}
+
+	int totalForEdges=0;
+
+	for(map<int,int>::iterator i=connectionFrequencies.begin();
+		i!=connectionFrequencies.end();i++){
+		totalForEdges+=i->second;
+	}
+
+	for(map<int,int>::iterator i=connectionFrequencies.begin();
+		i!=connectionFrequencies.end();i++){
+		f4<<"        "<<i->first<<"    "<<i->second<<"    "<<i->second*100.0/totalForEdges<<"%"<<endl;
+	}
+	
+	f4<<"        "<<"Total"<<"    "<<totalForEdges<<"    100.00%"<<endl;
+
+	f4<<"   Average: "<<getAverage(&connectivities)<<endl;
+	f4<<"   StandardDeviation: "<<getStandardDeviation(&connectivities)<<endl;
+
+	f4<<endl;
+	f4<<"NumberOfRelayEventsPerVertex"<<endl;
+
+	f4<<"   Average: "<<getAverage(&relayEvents)<<endl;
+	f4<<"   StandardDeviation: "<<getStandardDeviation(&relayEvents)<<endl;
+
+	f4<<endl;
+	f4<<"RouteLength"<<endl;
+
+	f4<<"   Frequencies:"<<endl;
+	map<int,int> pathLengths;
+
+	for(Rank i=0;i<m_size;i++){
+		for(Rank j=0;j<m_size;j++){
+			vector<Rank> route;
+			m_implementation->getRoute(i,j,&route);
+
+			// we remove the source vertex
+			pathLengths[route.size()-1]++;
+		}
+	}
+
+	int totalForPaths=0;
+	for(map<int,int>::iterator i=pathLengths.begin();
+		i!=pathLengths.end();i++){
+		totalForPaths+=i->second;
+	}
+
+	for(map<int,int>::iterator i=pathLengths.begin();
+		i!=pathLengths.end();i++){
+		f4<<"        "<<i->first<<"    "<<i->second<<"    "<<i->second*100.0/totalForPaths<<"%"<<endl;
+	}
+	f4<<"        "<<"Total"<<"    "<<totalForPaths<<"    100.00%"<<endl;
+
+	f4.close();
+
+}
+
+int ConnectionGraph::getNextRankInRoute(Rank source,Rank destination,Rank rank){
+	// TODO: replace by a switch case to avoid virtual calls
+	return m_implementation->getNextRankInRoute(source,destination,rank);
+}
+
+void ConnectionGraph::getIncomingConnections(Rank source,vector<Rank>*connections){
+	// TODO: replace by a switch case to avoid virtual calls
+	m_implementation->getIncomingConnections(source,connections);
+}
+
+void ConnectionGraph::buildGraph(int numberOfRanks,string type,bool verbosity,
+int degree){
+	m_verbose=verbosity;
+
+	m_size=numberOfRanks;
+
+	/** provide the user-provided degree for those
+ * requiring it */
+	m_deBruijn.setDegree(degree);
+	m_hypercube.setDegree(degree);
+
+	if(type==""){
+		type="debruijn";
+	}
+
+	m_implementation=NULL;
+
+	if(type=="random"){
+		m_implementation=&m_random;
+		m_typeCode=__RANDOM;
+	}else if((type=="hypercube"||type=="polytope")
+		 && m_hypercube.isValid(numberOfRanks)){
+
+		m_implementation=&m_hypercube;
+		m_typeCode=__HYPERCUBE;
+	}else if(type=="group"){
+		m_implementation=&m_group;
+		m_typeCode=__GROUP;
+	}else if(type=="debruijn" && m_deBruijn.isValid(numberOfRanks)){
+		m_implementation=&m_deBruijn;
+		m_typeCode=__DEBRUIJN;
+	}else if(type=="complete"){
+		m_implementation=&m_complete;
+		m_typeCode=__COMPLETE;
+	}else if(type=="kautz" && m_kautz.isValid(numberOfRanks)){
+		m_implementation=&m_kautz;
+		m_typeCode=__KAUTZ;
+	}else if(type=="experimental" && m_experimental.isValid(numberOfRanks)){
+		m_implementation=&m_experimental;
+		m_typeCode=__EXPERIMENTAL;
+	}else{
+		cout<<"Warning: using a complete graph because type "<<type<<" can not be used with "<<numberOfRanks<<" vertices"<<endl;
+		type="complete";
+		m_implementation=&m_complete;
+		m_typeCode=__COMPLETE;
+	}
+
+	m_type=type;
+	
+	// TODO: replace by a switch case to avoid virtual calls
+	m_implementation->setVerbosity(m_verbose);
+
+	// TODO: replace by a switch case to avoid virtual calls
+	m_implementation->makeConnections(m_size);
+
+	// TODO: replace by a switch case to avoid virtual calls
+	m_implementation->makeRoutes();
+}
+
+/**
+ * TODO: remove me
+ * */
+int ConnectionGraph::getRelaysFrom0(Rank rank){
+	return m_implementation->getRelaysFrom0(rank);
+}
+
+/**
+ * TODO: remove me
+ */
+int ConnectionGraph::getRelaysTo0(Rank rank){
+	return m_implementation->getRelaysTo0(rank);
+}
+
+void ConnectionGraph::printStatus(){
+
+	if(m_typeCode==__HYPERCUBE)
+		m_hypercube.printStatus(m_rank);
+}
+
+void ConnectionGraph::start(Rank rank){
+
+	m_rank=rank;
+
+	if(m_typeCode==__HYPERCUBE)
+		m_hypercube.start();
+}
diff --git a/RayPlatform/routing/ConnectionGraph.h b/RayPlatform/routing/ConnectionGraph.h
new file mode 100644
index 0000000..a7a3d84
--- /dev/null
+++ b/RayPlatform/routing/ConnectionGraph.h
@@ -0,0 +1,109 @@
+/*
+ 	RayPlatform
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _ConnectionGraph
+#define _ConnectionGraph
+
+#include <vector>
+#include <set>
+#include <map>
+#include <core/statistics.h>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <routing/GraphImplementation.h>
+#include <routing/GraphImplementationRandom.h>
+#include <routing/GraphImplementationGroup.h>
+#include <routing/GraphImplementationDeBruijn.h>
+#include <routing/GraphImplementationKautz.h>
+#include <routing/GraphImplementationExperimental.h>
+#include <routing/GraphImplementationComplete.h>
+#include <routing/Hypercube.h>
+#include <string>
+#include <core/types.h>
+using namespace std;
+
+/** a graph for connections between compute cores */
+class ConnectionGraph{
+
+	Rank m_rank;
+
+	string m_type;
+	int m_typeCode;
+
+	GraphImplementation*m_implementation;
+
+	GraphImplementationRandom m_random;
+	GraphImplementationComplete m_complete;
+	GraphImplementationDeBruijn m_deBruijn;
+	GraphImplementationKautz m_kautz;
+	GraphImplementationExperimental m_experimental;
+	GraphImplementationGroup m_group;
+	Hypercube m_hypercube;
+
+/** verbosity */
+	bool m_verbose;
+
+/**
+ * The number of ranks
+ */
+	int m_size;
+
+	/************************************************/
+	/** methods to build connections */
+
+	/** print a route */
+	void printRoute(Rank source,Rank destination);
+
+public:
+
+/**
+ * Get the next rank to relay the message after <rank> for the route between
+ * source and destination
+ */
+	Rank getNextRankInRoute(Rank source,Rank destination,Rank rank);
+
+/**
+ * Is there a up-link between a source and a destination
+ */
+	bool isConnected(Rank source,Rank destination);
+
+	void writeFiles(string prefix);
+
+/** build the graph. */
+	void buildGraph(int numberOfVertices,string method,bool verbosity,int degree);
+
+
+	/** get the number of paths that contain rank from 0 to any vertex 
+ * TODO: remove this */
+	int getRelaysFrom0(Rank rank);
+
+	/** get the number of paths that contain rank from any vertex to vertex 0  
+ * TODO: remove this */
+	int getRelaysTo0(Rank rank);
+
+	void getIncomingConnections(Rank i,vector<Rank>*connections);
+
+	void printStatus();
+	void start(Rank rank);
+};
+
+#endif
diff --git a/RayPlatform/routing/GraphImplementation.cpp b/RayPlatform/routing/GraphImplementation.cpp
new file mode 100644
index 0000000..57208ed
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementation.cpp
@@ -0,0 +1,352 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <routing/GraphImplementation.h>
+#include <iostream>
+#include <stdlib.h> /* srand, rand */
+#include <algorithm> /* random_shuffle */
+using namespace std;
+
+void GraphImplementation::getOutcomingConnections(Rank source,vector<Rank>*connections){
+	for(set<Rank>::iterator i=m_outcomingConnections[source].begin();
+		i!=m_outcomingConnections[source].end();i++){
+		connections->push_back(*i);
+	}
+}
+
+void GraphImplementation::getIncomingConnections(Rank source,vector<Rank>*connections){
+	for(set<Rank>::iterator i=m_incomingConnections[source].begin();
+		i!=m_incomingConnections[source].end();i++){
+		connections->push_back(*i);
+	}
+}
+
+/**
+ * Dijkstra's algorithm
+ * All weights are 1
+ *
+ * furthermore, we minimize saturation of vertices
+ * by minimizing the relay points
+ */
+void GraphImplementation::findShortestPath(Rank source,Rank destination,vector<Rank>*route){
+
+	// same vertex
+	if(source==destination){
+		route->push_back(source);
+		route->push_back(destination);
+		return;
+	}
+
+	// assign tentative distances
+	map<Rank,Distance> tentativeDistances;
+	
+	for(Rank i=0;i<m_size;i++)
+		tentativeDistances[i]=9999;
+
+	tentativeDistances[source]=0;
+
+	map<Rank,Rank> previousVertices;
+
+	// create a set of unvisited vertices
+	set<Rank> unvisited;
+
+	for(Rank i=0;i<m_size;i++)
+		unvisited.insert(i);
+
+	// create a current vertex
+	Rank current=source;
+
+	// create an index of distances
+	map<Distance,set<Rank> > verticesWithDistance;
+
+	for(map<Rank,Distance>::iterator i=tentativeDistances.begin();i!=tentativeDistances.end();i++){
+		verticesWithDistance[i->second].insert(i->first);
+	}
+
+	while(!unvisited.empty()){
+	
+		// calculate the tentative distance
+		// of each neighbors of the current
+		vector<int> connections;
+
+		getOutcomingConnections(current,&connections);
+
+		for(vector<Rank>::iterator neighbor=connections.begin();
+			neighbor!=connections.end();neighbor++){
+			Rank theNeighbor=*neighbor;
+
+			// we are only interested in unvisited neighbors
+			if(unvisited.count(theNeighbor)>0){
+				Distance newDistance=tentativeDistances[current]+1;
+				Distance oldDistance=tentativeDistances[theNeighbor];
+
+				// the new distance is better
+				// if the oldDistance for theNeighbor and the newDistance
+				// for theNeighbor in respect to current are equal, then
+				// choose the one having the previousVertex with the least
+				// relay events. The previous vertex is current or the one
+				// stored in previousVertices
+				if(newDistance < oldDistance || 
+					// distances are equal and current has less relay events
+				(newDistance==oldDistance && previousVertices.count(theNeighbor)>0
+				&& m_relayEvents[current] < m_relayEvents[previousVertices[theNeighbor]])){
+
+					tentativeDistances[theNeighbor]=newDistance;
+					previousVertices[theNeighbor]=current;
+
+					// update the distance index
+					verticesWithDistance[oldDistance].erase(theNeighbor);
+					verticesWithDistance[newDistance].insert(theNeighbor);
+				}
+			}
+		}
+
+		// mark the current vertex as not used
+		unvisited.erase(current);
+
+		// remove it as well from the index
+		Distance theDistance=tentativeDistances[current];
+		verticesWithDistance[theDistance].erase(current);
+
+		if(verticesWithDistance[theDistance].size()==0)
+			verticesWithDistance.erase(theDistance);
+
+		// the next current is the one in unvisited vertices
+		// with the lowest distance
+		
+		Distance bestDistance=-1;
+
+		// here we find the next current vertex
+		// find it using the index
+		// the index contains only unvisited vertices
+		for(map<Distance,set<Rank> >::iterator myIterator=verticesWithDistance.begin();
+			myIterator!=verticesWithDistance.end();myIterator++){
+
+			Distance theDistance=myIterator->first;
+
+			// we are done if all the remaining distances are greater
+			if(bestDistance!=-1 && theDistance > bestDistance)
+				break;
+
+			// find a vertex with the said distance
+			for(set<Rank>::iterator i=myIterator->second.begin();
+				i!=myIterator->second.end();i++){
+				Rank vertex=*i;
+
+				// the distance is lower or no distance
+				// was processed so far
+				if(theDistance < bestDistance || bestDistance==-1){
+					current=vertex;
+					bestDistance=tentativeDistances[vertex];
+
+					// we can break because all the other remaining 
+					// for this distance have the same distance (obviously)
+					break;
+				}
+			}
+		}
+	}
+
+	// generate the route
+	current=destination;
+	while(current!=source){
+		route->push_back(current);
+
+		/** this should not happen... */
+		if(previousVertices.count(current)==0){
+			cout<<"Error, current has no previous vertex:";
+			cout<<" there is no route between "<<source<<" and "<<destination<<endl;
+			route->clear();
+			return;
+		}
+
+		current=previousVertices[current];
+	}
+
+	route->push_back(source);
+
+	// invert the route
+	// because the one we have is from destination to source
+	int left=0;
+	int right=route->size()-1;
+	while(left<right){
+		Rank t=(*route)[left];
+		(*route)[left]=(*route)[right];
+		(*route)[right]=t;
+		left++;
+		right--;
+	}
+}
+
+void GraphImplementation::getRoute(Rank source,Rank destination,vector<Rank>*route){
+
+	Rank currentVertex=source;
+	route->push_back(currentVertex);
+
+	while(currentVertex!=destination){
+		currentVertex=getNextRankInRoute(source,destination,currentVertex);
+		route->push_back(currentVertex);
+	}
+}
+
+/**
+ * Compute the routing tables.
+ * This is done for all pairs of ranks
+ */
+void GraphImplementation::computeRoutes(){
+	// initialize the relay events
+	for(Rank source=0;source<m_size;source++){
+		m_relayEvents.push_back(0);
+	}
+
+	// append empty routes
+	for(Rank i=0;i<m_size;i++){
+		vector<map<Rank,Rank> > a;
+		for(Rank j=0;j<m_size;j++){
+			map<Rank,Rank> b;
+			a.push_back(b);
+		}
+		m_routes.push_back(a);
+	}
+
+	#ifdef CONFIG_ROUTER_VERBOSITY
+	int step=m_size/60+1;
+	#endif
+
+	// make a liste of pairs
+	vector<vector<Rank> > pairs;
+
+	for(Rank source=0;source<m_size;source++){
+		for(Rank destination=0;destination<m_size;destination++){
+			vector<Rank> pair;
+			pair.push_back(source);
+			pair.push_back(destination);
+			pairs.push_back(pair);
+		}
+	}
+
+	// shuffle the list
+	// we need the same seed on all ranks
+	// we shuffle a lot 
+	for(int i=0;i<32;i++){
+		srand(i*i + i*i*i);
+		std::random_shuffle(pairs.begin(),pairs.end());
+	}
+
+	if(m_verbose)
+		cout<<"Computing routes, please wait..."<<endl;
+
+	int done=0;
+
+	// compute routes using the random order
+	for(int i=0;i<(int)pairs.size();i++){
+
+		if(done%100==0 && m_verbose)
+			cout<<"makeRoutes "<<done<<"/"<<pairs.size()<<" "<<done/(0.0+pairs.size())*100<<"%"<<endl;
+
+		Rank source=pairs[i][0];
+		Rank destination=pairs[i][1];
+
+		vector<Rank> route;
+
+		computeRoute(source,destination,&route);
+
+		for(int i=0;i<(int)route.size()-1;i++){
+			// add the route
+			m_routes[source][destination][route[i]]=route[i+1];
+		}
+
+		// add the relay information
+		// the relay ranks are all the ranks in the route
+		// minus the source and minus the destination
+		for(int i=1;i<(int)route.size()-1;i++){
+			Rank relayRank=route[i];
+
+			// general relay data
+			m_relayEvents[relayRank]++;
+		}
+
+		done++;
+	}
+
+	cout<<"makeRoutes "<<done<<"/"<<pairs.size()<<" "<<done/(0.0+pairs.size())*100<<"%"<<endl;
+}
+
+void GraphImplementation::computeRelayEvents(){
+
+	m_relayEvents.clear();
+	m_relayEventsFrom0.clear();
+	m_relayEventsTo0.clear();
+
+	// initialize the relay events
+	for(Rank source=0;source<m_size;source++){
+		m_relayEvents.push_back(0);
+		m_relayEventsTo0.push_back(0);
+		m_relayEventsFrom0.push_back(0);
+	}
+
+	for(Rank source=0;source<m_size;source++){
+		if(source%100==0)
+			cout<<source<<"/"<<m_size<<endl;
+		for(Rank destination=0;destination<m_size;destination++){
+			vector<Rank> route;
+			getRoute(source,destination,&route);
+
+			// add the relay information
+			// the relay ranks are all the ranks in the route
+			// minus the source and minus the destination
+			for(int i=1;i<(int)route.size()-1;i++){
+				Rank relayRank=route[i];
+
+				// general relay data
+				m_relayEvents[relayRank]++;
+
+				// relay data from 0
+				if(source==0)
+					m_relayEventsFrom0[relayRank]++;
+	
+				// relay data to 0
+				if(destination==0)
+					m_relayEventsTo0[relayRank]++;
+			}
+	
+		}
+	}
+	
+	cout<<m_size<<"/"<<m_size<<endl;
+}
+
+int GraphImplementation::getRelaysFrom0(Rank rank){
+	return m_relayEventsFrom0[rank];
+}
+
+int GraphImplementation::getRelaysTo0(Rank rank){
+	return m_relayEventsTo0[rank];
+}
+
+int GraphImplementation::getRelays(Rank rank){
+	return m_relayEvents[rank];
+}
+
+void GraphImplementation::setVerbosity(bool verbosity){
+	m_verbose=verbosity;
+}
+
diff --git a/RayPlatform/routing/GraphImplementation.h b/RayPlatform/routing/GraphImplementation.h
new file mode 100644
index 0000000..2829aa6
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementation.h
@@ -0,0 +1,126 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _GraphImplementation_h
+#define _GraphImplementation_h
+
+#include <stdint.h>
+
+/**
+ * a tuple for message routing
+ * */
+class Tuple{
+public:
+	uint8_t m_digits[16];
+};
+
+#include <vector>
+#include <set>
+#include <map>
+#include <core/types.h>
+using namespace std;
+
+/** virtual interface for graphs */
+class GraphImplementation{
+
+protected:
+	bool m_verbose;
+
+	int m_size;
+
+/** 
+ * routes contained in the route tables
+ *
+ * data:
+ *
+ * source
+ * 	destination
+ * 		vertex1
+ * 			vertex2
+ */
+	vector<vector<map<Rank,Rank> > > m_routes;
+
+/**
+ * number of relays
+ */
+	vector<int> m_relayEvents;
+
+/**
+ * Number of relay events between any destination and source 0
+ */
+	vector<int> m_relayEventsTo0;
+
+/**
+ * Number of relay events between source 0 and any destination
+ */
+	vector<int> m_relayEventsFrom0;
+
+
+/**
+ * outcoming connections
+ */
+	vector<set<Rank> > m_outcomingConnections;
+
+/**
+ * incoming connections
+ */
+	vector<set<Rank> > m_incomingConnections;
+
+	void computeRoutes();
+
+	/** find the shortest path between a source and a destination */
+	void findShortestPath(Rank source,Rank destination,vector<Rank>*route);
+
+	void computeRelayEvents();
+
+	virtual void computeRoute(Rank a,Rank b,vector<Rank>*route) = 0;
+	
+public:
+
+	virtual void makeConnections(int n) =0;
+	
+	virtual void makeRoutes() = 0;
+
+/** get the next rank in a route */
+	virtual Rank getNextRankInRoute(Rank source,Rank destination,Rank rank) = 0;
+	
+	virtual bool isConnected(Rank i,Rank j) = 0;
+
+	virtual ~GraphImplementation(){ /* nothing */} /* and no trailing ; */
+
+	void getRoute(Rank source,Rank destination,vector<Rank>*route);
+
+/**
+ * Get the connections for a source
+ */
+	void getOutcomingConnections(Rank source,vector<Rank>*connections);
+
+	void getIncomingConnections(Rank rank,vector<Rank>*connections);
+
+	void setVerbosity(bool verbosity);
+
+	int getRelays(Rank rank);
+	int getRelaysTo0(Rank rank);
+	int getRelaysFrom0(Rank rank);
+};
+
+#endif
+
diff --git a/RayPlatform/routing/GraphImplementationComplete.cpp b/RayPlatform/routing/GraphImplementationComplete.cpp
new file mode 100644
index 0000000..d822a78
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationComplete.cpp
@@ -0,0 +1,65 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <routing/GraphImplementationComplete.h>
+
+/**
+ * complete graph
+ */
+void GraphImplementationComplete::makeConnections(int n){
+	m_size=n;
+
+	for(int i=0;i<m_size;i++){
+		set<Rank> b;
+		m_incomingConnections.push_back(b);
+		m_outcomingConnections.push_back(b);
+	}
+
+	for(Rank i=0;i<m_size;i++){
+		for(Rank j=0;j<m_size;j++){
+			if(i==j)
+				continue;
+
+			m_outcomingConnections[i].insert(j);
+			m_incomingConnections[j].insert(i);
+		}
+	}
+}
+
+void GraphImplementationComplete::computeRoute(Rank a,Rank b,vector<Rank>*route){
+	/* not necessary */
+}
+
+void GraphImplementationComplete::makeRoutes(){
+	/* no routes are computed */
+
+	computeRelayEvents();
+}
+
+Rank GraphImplementationComplete::getNextRankInRoute(Rank source,Rank destination,Rank rank){
+	return destination;
+}
+
+bool GraphImplementationComplete::isConnected(Rank source,Rank destination){
+	return true;
+}
+
+
diff --git a/RayPlatform/routing/GraphImplementationComplete.h b/RayPlatform/routing/GraphImplementationComplete.h
new file mode 100644
index 0000000..c97ec45
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationComplete.h
@@ -0,0 +1,45 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _GraphImplementationComplete_h
+#define _GraphImplementationComplete_h
+
+#include <routing/GraphImplementation.h>
+
+/**
+ * complete graph 
+ */
+class GraphImplementationComplete : public GraphImplementation{
+	
+protected:
+
+	void computeRoute(Rank a,Rank b,vector<Rank>*route);
+	Rank getNextRankInRoute(Rank source,Rank destination,Rank rank);
+
+	bool isConnected(Rank source,Rank destination);
+
+public:
+
+	void makeConnections(int n);
+	void makeRoutes();
+};
+
+#endif
diff --git a/RayPlatform/routing/GraphImplementationDeBruijn.cpp b/RayPlatform/routing/GraphImplementationDeBruijn.cpp
new file mode 100644
index 0000000..997b748
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationDeBruijn.cpp
@@ -0,0 +1,319 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+//#define CONFIG_ROUTING_DE_BRUIJN_COMPUTE_ROUTES
+
+#include <routing/GraphImplementationDeBruijn.h>
+#include <iostream>
+using namespace std;
+
+int GraphImplementationDeBruijn::getPower(int base,int exponent){
+	int a=1;
+	while(exponent--)
+		a*=base;
+	return a;
+}
+
+/**
+ *  convert a number to a de Bruijn vertex
+ */
+void GraphImplementationDeBruijn::convertToDeBruijn(int i,Tuple*tuple){
+	for(int power=0;power<m_diameter;power++){
+		int value=(i%getPower(m_base,power+1))/getPower(m_base,power);
+		tuple->m_digits[power]=value;
+	}
+}
+
+bool GraphImplementationDeBruijn::isAPowerOf(int n,int base){
+	int remaining=n;
+	
+	while(remaining>1){
+		if(remaining%base != 0)
+			return false;
+		remaining/=base;
+	}
+	return true;
+}
+
+void GraphImplementationDeBruijn::configureGraph(int n){
+	int base=-1;
+
+	int maxBase=1024;
+
+
+	// use the user-provided degree, if any
+	if(isAPowerOf(n,m_degree)){
+		maxBase=m_degree;
+	}
+
+	while(maxBase>=n)
+		maxBase/=2;
+
+	for(int i=maxBase;i>=2;i--){
+		if(isAPowerOf(n,i)){
+			base=i;
+			break;
+		}
+	}
+
+	if(base==-1){
+		cout<<"Error, "<<n<<" is not a power of anything."<<endl;
+		m_base=base;
+		return;
+	}
+
+	int digits=1;
+
+	while(n > getPower(base,digits)){
+		digits++;
+	}
+
+	m_base=base;
+	m_diameter=digits;
+	m_size=n;
+}
+
+void GraphImplementationDeBruijn::makeConnections(int n){
+
+	configureGraph(n);
+
+	if(m_verbose){
+		cout<<"[GraphImplementationDeBruijn::makeConnections] using "<<m_diameter<<" for diameter with base ";
+		cout<<m_base<<endl;
+		cout<<"[GraphImplementationDeBruijn::makeConnections] The MPI graph has "<<m_size<<" vertices"<<endl;
+		cout<<"[GraphImplementationDeBruijn::makeConnections] The de Bruijn graph has "<<m_size<<" vertices"<<endl;
+	}
+
+	for(Rank i=0;i<m_size;i++){
+		set<Rank> b;
+		m_outcomingConnections.push_back(b);
+		m_incomingConnections.push_back(b);
+	}
+
+	// populate vertices
+	for(Rank i=0;i<m_size;i++){
+		Tuple a;
+		convertToDeBruijn(i,&a);
+		m_graphToDeBruijn.push_back(a);
+	}
+
+	// make all connections.
+	for(Rank i=0;i<m_size;i++){
+		for(Rank j=0;j<m_size;j++){
+			if(computeConnection(i,j)){
+				m_outcomingConnections[i].insert(j);
+				m_incomingConnections[j].insert(i);
+			}
+		}
+	}
+}
+
+/* base m_base to base 10 */
+int GraphImplementationDeBruijn::convertToBase10(Tuple*vertex){
+	int a=0;
+	for(int i=0;i<m_diameter;i++){
+		a+=vertex->m_digits[i]*getPower(m_base,i);
+	}
+	return a;
+}
+
+void GraphImplementationDeBruijn::printVertex(Tuple*a){
+	for(int i=0;i<m_diameter;i++){
+		if(i!=0)
+			cout<<",";
+		cout<<a->m_digits[i];
+	}
+}
+
+/** with de Bruijn routing, no route are pre-computed at all */
+void GraphImplementationDeBruijn::computeRoute(Rank source,Rank destination,vector<Rank>*route){
+	/* do nothing because this is not utilised */
+
+	Rank currentVertex=source;
+	route->push_back(currentVertex);
+
+	while(currentVertex!=destination){
+		currentVertex=computeNextRankInRoute(source,destination,currentVertex);
+		route->push_back(currentVertex);
+	}
+}
+
+Rank GraphImplementationDeBruijn::getNextRankInRoute(Rank source,Rank destination,Rank rank){
+	#ifdef CONFIG_ROUTING_DE_BRUIJN_COMPUTE_ROUTES
+
+	#ifdef ASSERT
+	assert(m_routes[source][destination].count(rank)==1);
+	#endif
+
+	return m_routes[source][destination][rank];
+
+	#else /* compute it right away */
+
+	return computeNextRankInRoute(source,destination,rank);
+
+	#endif
+}
+
+/** with de Bruijn routing, no route are pre-computed at all */
+void GraphImplementationDeBruijn::makeRoutes(){
+	/* we don't compute any routes */
+	
+	#ifdef CONFIG_ROUTING_DE_BRUIJN_COMPUTE_ROUTES
+	computeRoutes();
+	#endif
+
+	/* compute relay points */
+	computeRelayEvents();
+}
+
+/** to get the next rank,
+ * we need to shift the current one time on the left
+ * then, we find the maximum overlap
+ * between the current and the destination
+ *
+ * This value is the index of the digit in destination
+ * that we want to append to the next rank in the route
+ *
+ *	// example:
+	//
+	// base = 16
+	// digits = 3
+	//
+	// source = (0,4,2)
+	// destination = (9,8,7)
+	//
+	// the path is
+	//
+	// (0,4,2) -> (4,2,9) -> (2,9,8) -> (9,8,7)
+	//
+	// so for sure we have to shift the current by one on the left
+	//
+	// then the problem is how to choose which symbol to add 
+	//
+	// let's say that
+	//
+	// current = (4,2,9)
+	//
+	// then we should return (2,9,8) rapidly
+	//
+	// source=(0,2,2)
+	// destination=(2,2,1)
+	//
+	// (0,2,2) -> (2,2,1)	
+
+	// here we need to choose a digit from the destination
+	// and append it to the next
+	// case 1 destination can be obtained with 1 shift, overlap is 2
+	// case 2 destination can be obtained with 2 shifts, overlap is 1
+	// case 3 ...
+	// case m_digits destination can be obtained with m_digits shifts, overlap is 0
+
+ */
+Rank GraphImplementationDeBruijn::computeNextRankInRoute(Rank source,Rank destination,Rank current){
+
+	Tuple*destinationVertex=&(m_graphToDeBruijn[destination]);
+	Tuple*currentVertex=&(m_graphToDeBruijn[current]);
+	
+	// do a left shift
+	Tuple next;
+	for(int i=1;i<m_diameter;i++){
+		next.m_digits[i-1]=currentVertex->m_digits[i];
+	}
+	
+	int overlapSize=getMaximumOverlap(currentVertex,destinationVertex);
+
+	// append the digit
+	next.m_digits[m_diameter-1]=destinationVertex->m_digits[overlapSize];
+	
+	int nextRank=convertToBase10(&next) % m_size;
+
+	return nextRank;
+}
+
+/**
+ * here we find the maximum overlap between
+ * 2 de Bruijn vertices
+ *
+ * we don't look for a perfect match
+ */
+int GraphImplementationDeBruijn::getMaximumOverlap(Tuple*a,Tuple*b){
+
+	// we don't verify if they are exact matches
+	// because if it would be the case, nothing would
+	// need to be routed anywhere
+	int numberOfMatches=m_diameter-1;
+
+	while(1){
+		// check for numberOfMatches
+		int positionInA=m_diameter-numberOfMatches;
+		int positionInB=0;
+
+		bool match=true;
+
+		while(positionInA<m_diameter){
+			if(a->m_digits[positionInA] != b->m_digits[positionInB]){
+				match=false;
+				break;
+			}
+			positionInA++;
+			positionInB++;
+		}
+
+		if(match)
+			return numberOfMatches;
+
+		numberOfMatches--;
+	}
+
+	return 0; /* will never be reached */
+}
+
+bool GraphImplementationDeBruijn::isConnected(Rank source,Rank destination){
+	if(source==destination)
+		return true;
+
+	return m_outcomingConnections[source].count(destination)==1;
+}
+
+/** just verify the de Bruijn property
+ * also, we allow any vertex to communicate with itself
+ * regardless of the de Bruijn property
+ */
+bool GraphImplementationDeBruijn::computeConnection(Rank source,Rank destination){
+
+	// otherwise, we look for the de Bruijn property
+	Tuple*sourceVertex=&(m_graphToDeBruijn[source]);
+	Tuple*destinationVertex=&(m_graphToDeBruijn[destination]);
+
+	int overlap=getMaximumOverlap(sourceVertex,destinationVertex);
+
+	return overlap==m_diameter-1;
+}
+
+bool GraphImplementationDeBruijn::isValid(int n){
+	configureGraph(n);
+
+	return m_base!=-1;
+}
+
+void GraphImplementationDeBruijn::setDegree(int degree){
+	m_degree=degree;
+}
diff --git a/RayPlatform/routing/GraphImplementationDeBruijn.h b/RayPlatform/routing/GraphImplementationDeBruijn.h
new file mode 100644
index 0000000..e1e4485
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationDeBruijn.h
@@ -0,0 +1,78 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _GraphImplementationDeBruijn_h
+#define _GraphImplementationDeBruijn_h
+
+#include <routing/GraphImplementation.h>
+#include <vector>
+#include <stdint.h>
+using namespace std;
+
+/**
+ * de Bruijn graph
+ * n must be a power of something
+ */
+class GraphImplementationDeBruijn : public GraphImplementation{
+
+	/** the user-provided degree */
+	int m_degree;
+
+	vector<Tuple> m_graphToDeBruijn;
+
+	int m_base;
+
+	int m_diameter;
+
+	void configureGraph(int n);
+
+	int getPower(int base,int exponent);
+
+/** convert a number to a de Bruijn vertex */
+	void convertToDeBruijn(int i,Tuple*tuple);
+
+/** convert a de Bruijn vertex to base 10 */
+	int convertToBase10(Tuple*vertex);
+
+	void printVertex(Tuple*a);
+	bool isAPowerOf(int n,int base);
+
+	int getMaximumOverlap(Tuple*a,Tuple*b);
+
+	Rank computeNextRankInRoute(Rank source,Rank destination,Rank rank);
+	bool computeConnection(Rank source,Rank destination);
+
+protected:
+
+	void computeRoute(Rank a,Rank b,vector<Rank>*route);
+	Rank getNextRankInRoute(Rank source,Rank destination,Rank rank);
+	bool isConnected(Rank source,Rank destination);
+public:
+
+	void makeConnections(int n);
+	void makeRoutes();
+
+	void setDegree(int degree);
+
+	bool isValid(int n);
+};
+
+#endif
diff --git a/RayPlatform/routing/GraphImplementationExperimental.cpp b/RayPlatform/routing/GraphImplementationExperimental.cpp
new file mode 100644
index 0000000..d86b71e
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationExperimental.cpp
@@ -0,0 +1,349 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+//#define CONFIG_ROUTING_KAUTZ_COMPUTE_ROUTES
+
+#include <routing/GraphImplementationExperimental.h>
+#include <iostream>
+using namespace std;
+
+int GraphImplementationExperimental::getPower(int base,int exponent){
+	int a=1;
+	while(exponent--)
+		a*=base;
+	return a;
+}
+
+/**
+ *  convert a number to a de Bruijn vertex
+ */
+void GraphImplementationExperimental::convertToBase(int i,Tuple*tuple){
+	for(int power=0;power<m_diameter;power++){
+		int value=(i%getPower(m_base,power+1))/getPower(m_base,power);
+		tuple->m_digits[power]=value;
+	}
+}
+
+bool GraphImplementationExperimental::isAPowerOf(int n,int base){
+	int remaining=n;
+	
+	while(remaining>1){
+		if(remaining%base != 0)
+			return false;
+		remaining/=base;
+	}
+	return true;
+}
+
+/**
+ * a Experimental vertex has no identical consecutive symbols
+ */
+bool GraphImplementationExperimental::isAExperimentalVertex(Tuple*vertex){
+	for(int i=0;i<m_diameter-m_zone+1;i++){
+		for(int j=0;j<m_zone;j++){
+			for(int k=j+1;k<m_zone;k++){
+				if(vertex->m_digits[i+j]==vertex->m_digits[i+k]){
+/*
+					cout<<"invalid ";
+					printVertex(vertex);
+					cout<<endl;
+*/
+					return false;
+				}
+			}
+		}
+	}
+/*
+	cout<<"valid ";
+	printVertex(vertex);
+	cout<<endl;
+*/
+	return true;
+}
+
+void GraphImplementationExperimental::configureGraph(int n){
+	// given a degree k and a diameter d,
+	// the number of vertices is (k+1)*k^(d-1)
+	//
+	// let's see if we can find a match.
+	
+	bool found=false;
+	for(int degree=2;degree<=1024;degree++){
+		for(int zone=3;zone<5;zone++){
+			for(int diameter=zone;diameter<10;diameter++){
+				int vertices=1;
+			
+				int p=1;
+				while(p<zone){
+					vertices*=(degree+p);
+					p++;
+				}
+
+				vertices*=getPower(degree,diameter-(zone-1));
+
+				if(vertices==n){
+					found=true;
+					m_degree=degree;
+					m_zone=zone;
+					m_diameter=diameter;
+					m_base=m_degree+m_zone-1;
+					m_size=n;
+		
+					break;
+				}
+			}
+		}
+	}
+
+	if(!found){
+		cout<<"Error: cannot create a Experimental graph with "<<n<<" vertices"<<endl;
+		m_base=-1;
+	}
+}
+
+void GraphImplementationExperimental::makeConnections(int n){
+	
+	configureGraph(n);
+
+	int iterator=0;
+
+	cout<<"[GraphImplementationExperimental::makeConnections] degree= "<<m_degree<<" diameter= "<<m_diameter;
+	cout<<" base= "<<m_base<<" zone= "<<m_zone<<" vertices= "<<n<<endl;
+
+	while((int)m_graphToExperimental.size()<n){
+		Tuple kautzVertex;
+		convertToBase(iterator,&kautzVertex);
+
+		if(isAExperimentalVertex(&kautzVertex)){
+			// direct mapping
+			m_graphToExperimental.push_back(kautzVertex);
+			
+			// reverse mapping
+			m_kautzToGraph[iterator]=m_graphToExperimental.size()-1;
+
+			cout<<"VERTEX "<<m_graphToExperimental.size()-1<<" is ";
+			printVertex(&kautzVertex);
+			cout<<endl;
+		}
+
+		iterator++;
+	}
+
+	// create empty lists
+	for(int i=0;i<m_size;i++){
+		set<Rank> b;
+		m_outcomingConnections.push_back(b);
+		m_incomingConnections.push_back(b);
+	}
+
+	// make all connections.
+	for(Rank i=0;i<m_size;i++){
+		for(Rank j=0;j<m_size;j++){
+			if(computeConnection(i,j)){
+				m_outcomingConnections[i].insert(j);
+				m_incomingConnections[j].insert(i);
+
+
+				cout<<"ARC "<<i<<" -> "<<j<<" is ";
+				printVertex(&(m_graphToExperimental[i]));
+				cout<<" -> ";
+				printVertex(&(m_graphToExperimental[j]));
+				cout<<endl;
+			}
+		}
+	}
+
+	cout<<"Done computing connections"<<endl;
+}
+
+/* base m_base to base 10 */
+int GraphImplementationExperimental::convertToBase10(Tuple*vertex){
+	int a=0;
+	for(int i=0;i<m_diameter;i++){
+		a+=vertex->m_digits[i]*getPower(m_base,i);
+	}
+	return a;
+}
+
+void GraphImplementationExperimental::printVertex(Tuple*a){
+	for(int i=0;i<m_diameter;i++){
+		if(i!=0)
+			cout<<",";
+		cout<<(int)a->m_digits[i];
+	}
+}
+
+/** with de Bruijn routing, no route are pre-computed at all */
+void GraphImplementationExperimental::computeRoute(Rank source,Rank destination,vector<Rank>*route){
+	/* do nothing because this is not utilised */
+
+	Rank currentVertex=source;
+	route->push_back(currentVertex);
+
+	while(currentVertex!=destination){
+		currentVertex=computeNextRankInRoute(source,destination,currentVertex);
+		route->push_back(currentVertex);
+	}
+}
+
+Rank GraphImplementationExperimental::getNextRankInRoute(Rank source,Rank destination,Rank rank){
+	#ifdef CONFIG_ROUTING_DE_KAUTZ_COMPUTE_ROUTES
+
+	#ifdef ASSERT
+	assert(m_routes[source][destination].count(rank)==1);
+	#endif
+
+	return m_routes[source][destination][rank];
+
+	#else /* compute it right away */
+
+	return computeNextRankInRoute(source,destination,rank);
+
+	#endif
+}
+
+/** with de Bruijn routing, no route are pre-computed at all */
+void GraphImplementationExperimental::makeRoutes(){
+	/* we don't compute any routes */
+	
+	#ifdef CONFIG_ROUTING_DE_KAUTZ_COMPUTE_ROUTES
+	computeRoutes();
+	#endif
+
+	/* compute relay points */
+	computeRelayEvents();
+}
+
+/** to get the next rank,
+ * we need to shift the current one time on the left
+ * then, we find the maximum overlap
+ * between the current and the destination
+ *
+ * This value is the index of the digit in destination
+ * that we want to append to the next rank in the route
+ */
+Rank GraphImplementationExperimental::computeNextRankInRoute(Rank source,Rank destination,Rank current){
+
+	cout<<"computeNextRankInRoute source: "<<source<<" current: "<<current<<" destination: "<<destination<<endl;
+
+	Tuple*currentVertex=&(m_graphToExperimental[current]);
+	Tuple*destinationVertex=&(m_graphToExperimental[destination]);
+
+	// do a left shift
+	Tuple next;
+	for(int i=1;i<m_diameter;i++){
+		next.m_digits[i-1]=currentVertex->m_digits[i];
+	}
+	
+	cout<<"current ";
+	printVertex(currentVertex);
+	cout<<endl;
+	cout<<"destination ";
+	printVertex(destinationVertex);
+	cout<<endl;
+
+	int overlapSize=getMaximumOverlap(currentVertex,destinationVertex);
+
+	cout<<"overlap is "<<overlapSize<<endl;
+
+	// append the digit
+	next.m_digits[m_diameter-1]=destinationVertex->m_digits[overlapSize];
+	
+	cout<<"next ";
+	printVertex(&next);
+	cout<<endl;
+
+	int inBase10=convertToBase10(&next);
+
+	// get the corresponding MPI rank for the Experimental vertex
+	int nextRank=m_kautzToGraph[inBase10];
+
+	return nextRank;
+}
+
+/**
+ * here we find the maximum overlap between
+ * 2 de Bruijn vertices
+ *
+ * we don't look for a perfect match
+ */
+int GraphImplementationExperimental::getMaximumOverlap(Tuple*a,Tuple*b){
+
+	// we don't verify if they are exact matches
+	// because if it would be the case, nothing would
+	// need to be routed anywhere
+	int numberOfMatches=m_diameter-1;
+
+	while(1){
+		// check for numberOfMatches
+		int positionInA=m_diameter-numberOfMatches;
+		int positionInB=0;
+
+		bool match=true;
+
+		while(positionInA<m_diameter){
+			if(a->m_digits[positionInA] != b->m_digits[positionInB]){
+				match=false;
+				break;
+			}
+			positionInA++;
+			positionInB++;
+		}
+
+		if(match)
+			return numberOfMatches;
+
+		numberOfMatches--;
+	}
+
+	return 0; /* will never be reached */
+}
+
+bool GraphImplementationExperimental::isConnected(Rank source,Rank destination){
+	if(source==destination)
+		return true;
+
+	return m_outcomingConnections[source].count(destination)==1;
+}
+
+/** 
+ * just verify the overlap property
+ */
+bool GraphImplementationExperimental::computeConnection(Rank source,Rank destination){
+
+	// fetch the tuples from the cache table
+	Tuple*sourceVertex=&(m_graphToExperimental[source]);
+	Tuple*destinationVertex=&(m_graphToExperimental[destination]);
+
+	// compute the maximum overlap
+	int overlap=getMaximumOverlap(sourceVertex,destinationVertex);
+
+	bool connected=overlap==m_diameter-1;
+
+	return connected;
+}
+
+bool GraphImplementationExperimental::isValid(int n){
+	configureGraph(n);
+
+	return m_base!=-1;
+}
+
diff --git a/RayPlatform/routing/GraphImplementationExperimental.h b/RayPlatform/routing/GraphImplementationExperimental.h
new file mode 100644
index 0000000..239261c
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationExperimental.h
@@ -0,0 +1,88 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _GraphImplementationExperimental_h
+#define _GraphImplementationExperimental_h
+
+#include <routing/GraphImplementation.h>
+#include <vector>
+#include <stdint.h>
+using namespace std;
+
+/**
+ * de Bruijn graph
+ * n must be a power of something
+ * \see http://www.sciencedirect.com/science/article/pii/S0140366497000741
+ *
+ * \see http://pl.atyp.us/wordpress/index.php/2007/12/the-kautz-graph/
+ *
+ * \see http://planetmath.org/encyclopedia/ExperimentalGraph.html
+ *
+ * \see http://www.sciencedirect.com/science/article/pii/089812219500146P
+ *
+ */
+class GraphImplementationExperimental: public GraphImplementation{
+
+	int m_zone;
+
+	vector<Tuple> m_graphToExperimental;
+
+	map<int,int> m_kautzToGraph;
+
+	int m_degree;
+
+	int m_base;
+
+	int m_diameter;
+
+	void configureGraph(int n);
+
+	int getPower(int base,int exponent);
+
+/** convert a number to another base */
+	void convertToBase(int i,Tuple*tuple);
+
+/** convert a vertex to base 10 */
+	int convertToBase10(Tuple*vertex);
+
+	void printVertex(Tuple*a);
+	bool isAPowerOf(int n,int base);
+
+	int getMaximumOverlap(Tuple*a,Tuple*b);
+
+	Rank computeNextRankInRoute(Rank source,Rank destination,Rank rank);
+	bool computeConnection(Rank source,Rank destination);
+	bool isAExperimentalVertex(Tuple*vertex);
+
+protected:
+
+	void computeRoute(Rank a,Rank b,vector<Rank>*route);
+	Rank getNextRankInRoute(Rank source,Rank destination,Rank rank);
+	bool isConnected(Rank source,Rank destination);
+public:
+
+	void makeConnections(int n);
+	void makeRoutes();
+
+	bool isValid(int n);
+};
+
+#endif
diff --git a/RayPlatform/routing/GraphImplementationGroup.cpp b/RayPlatform/routing/GraphImplementationGroup.cpp
new file mode 100644
index 0000000..8648fa5
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationGroup.cpp
@@ -0,0 +1,146 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <routing/GraphImplementationGroup.h>
+#include <assert.h>
+
+/**
+ * Get an intermediate for the type group
+ */
+int GraphImplementationGroup::getIntermediateRank(Rank rank){
+	return rank-rank % m_coresPerNode;
+}
+
+/**
+ * given n ranks, they are grouped in groups.
+ * in each group, only one rank is allowed to communicate with the reprentative rank of
+ * other groups.
+ *
+ * a rank can communicate with itself and with its intermediate rank
+ *
+ * if a rank is intermediate, it can reach any intermediate rank too.
+ *
+ * This maps well on super-computers with the same number of cores on each node
+ *
+ * For instance, if a node has 8 cores, then 8 ranks per group is correct.
+ *
+ * this method populates these attributes:
+ *
+ * 	- m_connections
+ * 	- m_routes
+ */
+void GraphImplementationGroup::makeConnections(int n){
+	m_coresPerNode=8;
+
+	m_size=n;
+
+	for(int i=0;i<m_size;i++){
+		set<Rank> b;
+		m_incomingConnections.push_back(b);
+		m_outcomingConnections.push_back(b);
+	}
+
+
+// the general idea of routing a message:
+//
+//
+// Cases: (starting with simpler cases)
+//
+//
+// case 1: source and destination are the same (1 hop, no routing required)
+// case 2:  source and destination are allowed to communicate (1 hop, no routing required)
+//   happens when 
+//       - source is the intermediate rank of the destination
+//       or
+//       - destination is the intermediate rank of the source
+// case 3:  source and destination share the same intermediate rank (2 hops, some routing)
+// case 4:  source and destination don't share the same intermediate rank (3 hops, full routing)
+//
+//
+// see Documentation/Message-Routing.txt
+//
+//             1	                 2                              3
+// trueSource -> sourceIntermediateRank -> destinationIntermediateRank -> trueDestination
+
+// the message has no routing tag
+// we must check that the channel is authorized.
+
+	for(Rank source=0;source<m_size;source++){
+		int intermediateSource=getIntermediateRank(source);
+	
+		// can connect with the intermediate source
+		m_outcomingConnections[source].insert(intermediateSource);
+		m_incomingConnections[intermediateSource].insert(source);
+
+		for(Rank destination=0;destination<m_size;destination++){
+
+			int intermediateDestination=getIntermediateRank(destination);
+
+			// an intermediate node can connect with any intermediate node
+			if(destination==intermediateDestination && source==intermediateSource){
+				m_outcomingConnections[source].insert(intermediateDestination);
+				m_incomingConnections[intermediateDestination].insert(source);
+			}
+			
+			// if the source is the intermediate destination, add a link
+			// this is within the same group
+			if(source==intermediateDestination){
+				m_outcomingConnections[source].insert(destination);
+				m_incomingConnections[destination].insert(source);
+			}
+
+			// peers in the same group are allowed to connect
+			if(intermediateSource==intermediateDestination){
+				m_outcomingConnections[source].insert(destination);
+				m_incomingConnections[destination].insert(source);
+			}
+		}
+	}
+}
+
+void GraphImplementationGroup::computeRoute(Rank a,Rank b,vector<Rank>*route){
+	findShortestPath(a,b,route);
+}
+
+void GraphImplementationGroup::makeRoutes(){
+	computeRoutes();
+
+	computeRelayEvents();
+}
+
+Rank GraphImplementationGroup::getNextRankInRoute(Rank source,Rank destination,Rank rank){
+	#ifdef ASSERT
+	assert(m_routes[source][destination].count(rank)==1);
+	#endif
+
+	return m_routes[source][destination][rank];
+}
+
+bool GraphImplementationGroup::isConnected(Rank source,Rank destination){
+	// communicating with itself is always allowed
+	if(source==destination)
+		return true;
+
+	// check that a connection exists
+	return m_outcomingConnections[source].count(destination)>0;
+}
+
+
diff --git a/RayPlatform/routing/GraphImplementationGroup.h b/RayPlatform/routing/GraphImplementationGroup.h
new file mode 100644
index 0000000..26fe6a1
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationGroup.h
@@ -0,0 +1,52 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _GraphImplementationGroup_h
+#define _GraphImplementationGroup_h
+
+#include <routing/GraphImplementation.h>
+
+/**
+ * Graph with groups
+ */
+class GraphImplementationGroup : public GraphImplementation{
+
+/**
+ * Number of cores for the group sub-command.
+ * Only useful with -route-messages -connection-type group -cores-per-node X
+ */
+	int m_coresPerNode;
+
+	int getIntermediateRank(Rank rank);
+	
+protected:
+
+	void computeRoute(Rank a,Rank b,vector<Rank>*route);
+	bool isConnected(Rank source,Rank destination);
+	Rank getNextRankInRoute(Rank source,Rank destination,Rank rank);
+
+public:
+
+	void makeConnections(int n);
+	void makeRoutes();
+};
+
+#endif
diff --git a/RayPlatform/routing/GraphImplementationKautz.cpp b/RayPlatform/routing/GraphImplementationKautz.cpp
new file mode 100644
index 0000000..7390f75
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationKautz.cpp
@@ -0,0 +1,295 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+//#define CONFIG_ROUTING_KAUTZ_COMPUTE_ROUTES
+
+#include <routing/GraphImplementationKautz.h>
+#include <iostream>
+using namespace std;
+
+int GraphImplementationKautz::getPower(int base,int exponent){
+	int a=1;
+	while(exponent--)
+		a*=base;
+	return a;
+}
+
+/**
+ *  convert a number to a de Bruijn vertex
+ */
+void GraphImplementationKautz::convertToBase(int i,Tuple*tuple){
+	for(int power=0;power<m_diameter;power++){
+		int value=(i%getPower(m_base,power+1))/getPower(m_base,power);
+		tuple->m_digits[power]=value;
+	}
+}
+
+bool GraphImplementationKautz::isAPowerOf(int n,int base){
+	int remaining=n;
+	
+	while(remaining>1){
+		if(remaining%base != 0)
+			return false;
+		remaining/=base;
+	}
+	return true;
+}
+
+/**
+ * a Kautz vertex has no identical consecutive symbols
+ */
+bool GraphImplementationKautz::isAKautzVertex(Tuple*vertex){
+	for(int i=0;i<m_diameter-1;i++){
+		if(vertex->m_digits[i]==vertex->m_digits[i+1])
+			return false;
+	}
+	return true;
+}
+
+void GraphImplementationKautz::configureGraph(int n){
+	// given a degree k and a diameter d,
+	// the number of vertices is (k+1)*k^(d-1)
+	//
+	// let's see if we can find a match.
+	
+	bool found=false;
+	for(int degree=2;degree<=1024;degree++){
+		for(int diameter=2;diameter<10;diameter++){
+			int vertices=(degree+1)*getPower(degree,diameter-1);
+			if(vertices==n){
+				found=true;
+				m_degree=degree;
+				m_diameter=diameter;
+				m_base=m_degree+1;
+				m_size=n;
+		
+				break;
+			}
+		}
+	}
+
+	if(!found){
+		cout<<"Error: cannot create a Kautz graph with "<<n<<" vertices"<<endl;
+		m_base=-1;
+	}
+}
+
+void GraphImplementationKautz::makeConnections(int n){
+	
+	configureGraph(n);
+
+	int iterator=0;
+
+	cout<<"[GraphImplementationKautz::makeConnections] degree= "<<m_degree<<" diameter= "<<m_diameter;
+	cout<<" base= "<<m_base<<" vertices= "<<n<<endl;
+
+	while((int)m_graphToKautz.size()<n){
+		Tuple kautzVertex;
+		convertToBase(iterator,&kautzVertex);
+
+		if(isAKautzVertex(&kautzVertex)){
+			// direct mapping
+			m_graphToKautz.push_back(kautzVertex);
+			
+			// reverse mapping
+			m_kautzToGraph[iterator]=m_graphToKautz.size()-1;
+		}
+
+		iterator++;
+	}
+
+	// create empty lists
+	for(int i=0;i<m_size;i++){
+		set<Rank> b;
+		m_outcomingConnections.push_back(b);
+		m_incomingConnections.push_back(b);
+	}
+
+	// make all connections.
+	for(Rank i=0;i<m_size;i++){
+		for(Rank j=0;j<m_size;j++){
+			if(computeConnection(i,j)){
+				m_outcomingConnections[i].insert(j);
+				m_incomingConnections[j].insert(i);
+			}
+		}
+	}
+
+	cout<<"Done computing connections"<<endl;
+}
+
+/* base m_base to base 10 */
+int GraphImplementationKautz::convertToBase10(Tuple*vertex){
+	int a=0;
+	for(int i=0;i<m_diameter;i++){
+		a+=vertex->m_digits[i]*getPower(m_base,i);
+	}
+	return a;
+}
+
+void GraphImplementationKautz::printVertex(Tuple*a){
+	for(int i=0;i<m_diameter;i++){
+		if(i!=0)
+			cout<<",";
+		cout<<(int)a->m_digits[i];
+	}
+}
+
+/** with de Bruijn routing, no route are pre-computed at all */
+void GraphImplementationKautz::computeRoute(Rank source,Rank destination,vector<Rank>*route){
+	/* do nothing because this is not utilised */
+
+	Rank currentVertex=source;
+	route->push_back(currentVertex);
+
+	while(currentVertex!=destination){
+		currentVertex=computeNextRankInRoute(source,destination,currentVertex);
+		route->push_back(currentVertex);
+	}
+}
+
+Rank GraphImplementationKautz::getNextRankInRoute(Rank source,Rank destination,Rank rank){
+	#ifdef CONFIG_ROUTING_DE_KAUTZ_COMPUTE_ROUTES
+
+	#ifdef ASSERT
+	assert(m_routes[source][destination].count(rank)==1);
+	#endif
+
+	return m_routes[source][destination][rank];
+
+	#else /* compute it right away */
+
+	return computeNextRankInRoute(source,destination,rank);
+
+	#endif
+}
+
+/** with de Bruijn routing, no route are pre-computed at all */
+void GraphImplementationKautz::makeRoutes(){
+	/* we don't compute any routes */
+	
+	#ifdef CONFIG_ROUTING_DE_KAUTZ_COMPUTE_ROUTES
+	computeRoutes();
+	#endif
+
+	/* compute relay points */
+	computeRelayEvents();
+}
+
+/** to get the next rank,
+ * we need to shift the current one time on the left
+ * then, we find the maximum overlap
+ * between the current and the destination
+ *
+ * This value is the index of the digit in destination
+ * that we want to append to the next rank in the route
+ */
+Rank GraphImplementationKautz::computeNextRankInRoute(Rank source,Rank destination,Rank current){
+	Tuple*currentVertex=&(m_graphToKautz[current]);
+	Tuple*destinationVertex=&(m_graphToKautz[destination]);
+
+	// do a left shift
+	Tuple next;
+	for(int i=1;i<m_diameter;i++){
+		next.m_digits[i-1]=currentVertex->m_digits[i];
+	}
+	
+	int overlapSize=getMaximumOverlap(currentVertex,destinationVertex);
+
+	// append the digit
+	next.m_digits[m_diameter-1]=destinationVertex->m_digits[overlapSize];
+	
+	int inBase10=convertToBase10(&next);
+
+	// get the corresponding MPI rank for the Kautz vertex
+	int nextRank=m_kautzToGraph[inBase10];
+
+	return nextRank;
+}
+
+/**
+ * here we find the maximum overlap between
+ * 2 de Bruijn vertices
+ *
+ * we don't look for a perfect match
+ */
+int GraphImplementationKautz::getMaximumOverlap(Tuple*a,Tuple*b){
+
+	// we don't verify if they are exact matches
+	// because if it would be the case, nothing would
+	// need to be routed anywhere
+	int numberOfMatches=m_diameter-1;
+
+	while(1){
+		// check for numberOfMatches
+		int positionInA=m_diameter-numberOfMatches;
+		int positionInB=0;
+
+		bool match=true;
+
+		while(positionInA<m_diameter){
+			if(a->m_digits[positionInA] != b->m_digits[positionInB]){
+				match=false;
+				break;
+			}
+			positionInA++;
+			positionInB++;
+		}
+
+		if(match)
+			return numberOfMatches;
+
+		numberOfMatches--;
+	}
+
+	return 0; /* will never be reached */
+}
+
+bool GraphImplementationKautz::isConnected(Rank source,Rank destination){
+	if(source==destination)
+		return true;
+
+	return m_outcomingConnections[source].count(destination)==1;
+}
+
+/** 
+ * just verify the overlap property
+ */
+bool GraphImplementationKautz::computeConnection(Rank source,Rank destination){
+
+	// fetch the tuples from the cache table
+	Tuple*sourceVertex=&(m_graphToKautz[source]);
+	Tuple*destinationVertex=&(m_graphToKautz[destination]);
+
+	// compute the maximum overlap
+	int overlap=getMaximumOverlap(sourceVertex,destinationVertex);
+
+	bool connected=overlap==m_diameter-1;
+
+	return connected;
+}
+
+bool GraphImplementationKautz::isValid(int n){
+	configureGraph(n);
+
+	return m_base!=-1;
+}
+
diff --git a/RayPlatform/routing/GraphImplementationKautz.h b/RayPlatform/routing/GraphImplementationKautz.h
new file mode 100644
index 0000000..b0cd50b
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationKautz.h
@@ -0,0 +1,86 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _GraphImplementationKautz_h
+#define _GraphImplementationKautz_h
+
+#include <routing/GraphImplementation.h>
+#include <vector>
+#include <stdint.h>
+using namespace std;
+
+/**
+ * Kautz graph
+ * n must be a power of something
+ * \see http://www.sciencedirect.com/science/article/pii/S0140366497000741
+ *
+ * \see http://pl.atyp.us/wordpress/index.php/2007/12/the-kautz-graph/
+ *
+ * \see http://planetmath.org/encyclopedia/KautzGraph.html
+ *
+ * \see http://www.sciencedirect.com/science/article/pii/089812219500146P
+ *
+ */
+class GraphImplementationKautz: public GraphImplementation{
+
+	vector<Tuple> m_graphToKautz;
+
+	map<int,int> m_kautzToGraph;
+
+	int m_degree;
+
+	int m_base;
+
+	int m_diameter;
+
+	void configureGraph(int n);
+
+	int getPower(int base,int exponent);
+
+/** convert a number to another base */
+	void convertToBase(int i,Tuple*tuple);
+
+/** convert a vertex to base 10 */
+	int convertToBase10(Tuple*vertex);
+
+	void printVertex(Tuple*a);
+	bool isAPowerOf(int n,int base);
+
+	int getMaximumOverlap(Tuple*a,Tuple*b);
+
+	Rank computeNextRankInRoute(Rank source,Rank destination,Rank rank);
+	bool computeConnection(Rank source,Rank destination);
+	bool isAKautzVertex(Tuple*vertex);
+
+protected:
+
+	void computeRoute(Rank a,Rank b,vector<Rank>*route);
+	Rank getNextRankInRoute(Rank source,Rank destination,Rank rank);
+	bool isConnected(Rank source,Rank destination);
+public:
+
+	void makeConnections(int n);
+	void makeRoutes();
+
+	bool isValid(int n);
+};
+
+#endif
diff --git a/RayPlatform/routing/GraphImplementationRandom.cpp b/RayPlatform/routing/GraphImplementationRandom.cpp
new file mode 100644
index 0000000..349c9f9
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationRandom.cpp
@@ -0,0 +1,115 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <routing/GraphImplementationRandom.h>
+#include <math.h> /* for log */
+#include <algorithm> /* random_shuffle */
+#include <assert.h>
+
+void GraphImplementationRandom::makeConnections(int n){
+	m_size=n;
+
+	for(int i=0;i<m_size;i++){
+		set<Rank> b;
+		m_outcomingConnections.push_back(b);
+		m_incomingConnections.push_back(b);
+	}
+
+	// create a set of all edges
+	vector<vector<Rank> > edges;
+	vector<int> identifiers;
+	int k=0;
+	for(Rank i=0;i<m_size;i++){
+		for(Rank j=0;j<m_size;j++){
+			// don't generate a pair for (i,i)
+			if(i==j)
+				continue;
+		
+			// don't generate a pair for (i,j) if i<j because
+			// (j,i) will be processed anyway
+			if(i<j)
+				continue;
+
+			vector<Rank> pair;
+			pair.push_back(i);
+			pair.push_back(j);
+			edges.push_back(pair);
+
+			identifiers.push_back(k);
+
+			k++;
+		}
+	}
+
+	// shuffle the edges
+	// we shuffle a lot
+	for(int i=0;i<32;i++){
+		srand(i*i*i+2*i);
+		std::random_shuffle(identifiers.begin(),identifiers.end());
+	}
+
+	// add the edges
+	int connectionsPerVertex=(int) (log(m_size)/log(2));
+	int numberOfEdgesToAdd=m_size*connectionsPerVertex/2;
+
+	// the first numberOfEdgesToAdd edges
+	for(int i=0;i<numberOfEdgesToAdd;i++){
+		int identifier=identifiers[i];
+		Rank source=edges[identifier][0];
+		Rank destination=edges[identifier][1];
+
+		// add the edge in both directions
+		m_outcomingConnections[source].insert(destination);
+		m_outcomingConnections[destination].insert(source);
+
+		m_incomingConnections[destination].insert(source);
+		m_incomingConnections[source].insert(destination);
+	}
+}
+
+void GraphImplementationRandom::computeRoute(Rank a,Rank b,vector<Rank>*route){
+	findShortestPath(a,b,route);
+}
+
+Rank GraphImplementationRandom::getNextRankInRoute(Rank source,Rank destination,Rank rank){
+	#ifdef ASSERT
+	assert(m_routes[source][destination].count(rank)==1);
+	#endif
+
+	return m_routes[source][destination][rank];
+}
+
+void GraphImplementationRandom::makeRoutes(){
+	computeRoutes();
+
+	computeRelayEvents();
+}
+
+bool GraphImplementationRandom::isConnected(Rank source,Rank destination){
+	// communicating with itself is always allowed
+	if(source==destination)
+		return true;
+
+	// check that a connection exists
+	return m_outcomingConnections[source].count(destination)>0;
+}
+
+
diff --git a/RayPlatform/routing/GraphImplementationRandom.h b/RayPlatform/routing/GraphImplementationRandom.h
new file mode 100644
index 0000000..136bf65
--- /dev/null
+++ b/RayPlatform/routing/GraphImplementationRandom.h
@@ -0,0 +1,44 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _GraphImplementationRandom_h
+#define _GraphImplementationRandom_h
+
+#include <routing/GraphImplementation.h>
+
+/**
+ * random graph with n*log(n)/2 edges
+ */
+class GraphImplementationRandom : public GraphImplementation{
+
+protected:
+	void computeRoute(Rank a,Rank b,vector<Rank>*route);
+
+	Rank getNextRankInRoute(Rank source,Rank destination,Rank rank);
+	bool isConnected(Rank source,Rank destination);
+public:
+
+	void makeConnections(int n);
+	void makeRoutes();
+
+};
+
+#endif
diff --git a/RayPlatform/routing/Hypercube.cpp b/RayPlatform/routing/Hypercube.cpp
new file mode 100644
index 0000000..c8081c2
--- /dev/null
+++ b/RayPlatform/routing/Hypercube.cpp
@@ -0,0 +1,664 @@
+/*
+ 	RayPlatform
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <routing/Hypercube.h>
+#include <iostream>
+using namespace std;
+
+#ifdef ASSERT
+#include <assert.h>
+#endif /* ASSERT */
+
+#define __INVALID_ALPHABET_SIZE -1
+
+/**
+ * TODO: move this upstream
+ */
+int Hypercube::getPower(int base,int exponent){
+	int a=1;
+	while(exponent--)
+		a*=base;
+	return a;
+}
+
+/**
+ * TODO: move this upstream
+ *  convert a number to a vertex
+ */
+void Hypercube::convertToVertex(int i,Tuple*tuple){
+	for(int power=0;power<m_wordLength;power++){
+		int value=(i%getPower(m_alphabetSize,power+1))/getPower(m_alphabetSize,power);
+		tuple->m_digits[power]=value;
+	}
+}
+
+/**
+ * TODO: move this upstream
+ */
+bool Hypercube::isAPowerOf(int n,int base){
+	int remaining=n;
+	
+	while(remaining>1){
+		if(remaining%base != 0)
+			return false;
+		remaining/=base;
+	}
+	return true;
+}
+
+/**
+ * only implemented for the hypercube with alphabet {0,1}
+ */
+void Hypercube::configureGraph(int n){
+
+	#if 0
+	// test some cases
+	n=1024;
+	m_degree=62;
+	#endif
+
+	int base=2;
+
+	// Given alphabetSize and wordLength,
+	//
+	// we have 
+	//      numberOfVertices := alphabetSize^wordLength  (1)
+	//
+	//       <=>
+	//
+	//      wordLength := log(numberOfVertices)/log(alphabetSize) (1.1)
+	//
+	// and
+	//      degree := (alphabetSize-1)*wordLength        (2)
+	//
+	//       <=>
+	//
+	//	wordLength := degree / (alphabetSize-1)      (2.1)
+	//
+	//	Now we have:
+	//
+	//	log(numberOfVertices)/log(alphabetSize) = degree / (alphabetSize-1)
+	//
+	//	or
+	//
+	//	(alphabetSize -1) * log(numberOfVertices) = degree * log(alphabetSize)
+	//
+	// The alphabetSize of a hypercube is 2.
+	//
+	// However, we can build similar things to a hypercube
+	// with a different alphabetSize
+	//
+	// alphabetSize=2, 1024 vertices
+	//
+	//
+	//
+	// we add an edge if u and v have exactly
+	// 1 different symbol in their tuple representation
+
+	// use the user-provided degree, if any
+	//
+	// TODO: try to use the provided degree
+	// see equations above...
+	#if 0
+	if(isAPowerOf(n,m_degree) && false){
+		maxBase=m_degree;
+	}
+	#endif
+
+	#if 0
+	while(maxBase>=n)
+		maxBase/=2;
+	#endif
+
+	#if 0
+	for(int i=maxBase;i>=2;i--){
+		if(isAPowerOf(n,i)){
+			base=i;
+			break;
+		}
+	}
+	#endif
+
+	/* try to modify the base such that base^exponent = vertices */
+	/* and that meets the provided degree. */
+
+	for(int alphabetSize=n-1;alphabetSize>=2;alphabetSize--){
+		int wordLength=1;
+
+		while(n > getPower(alphabetSize,wordLength)){
+			wordLength++;
+		}
+
+		if(n == getPower(alphabetSize,wordLength)){
+			int degree=(alphabetSize-1)*wordLength;
+			if(degree==m_degree){
+				cout<<"[Hypercube] found a hypercube topology that matches the provided degree "<<m_degree<<endl;
+
+				base=alphabetSize;
+			}
+		}
+	}
+
+
+	if(!isAPowerOf(n,base)){
+		cout<<"Error: "<<n<<" is not a power of 2, can not use the hypercube."<<endl;
+		m_alphabetSize=__INVALID_ALPHABET_SIZE;
+		return;
+	}
+
+	int digits=1;
+
+	while(n > getPower(base,digits)){
+		digits++;
+	}
+
+	#ifdef ASSERT
+	assert(n==getPower(base,digits));
+	#endif
+
+	m_alphabetSize=base; // this is alphabetSize
+	m_wordLength=digits; // this is wordLength
+	m_size=n; // this is the number of vertices
+
+	cout<<"[Hypercube] Size: "<<m_size<<" AlphabetSize: "<<m_alphabetSize<<" WordLength: "<<m_wordLength<<" Degree: "<<m_degree<<endl;
+	start();
+}
+
+void Hypercube::setLoad(int position,int symbol,uint64_t value){
+	m_loadValues[position*m_alphabetSize+symbol]=value;
+}
+
+uint64_t Hypercube::getLoad(int position,int symbol){
+	
+	#ifdef ASSERT
+	assert(position<m_wordLength);
+	assert(symbol<m_alphabetSize);
+	#endif /* ASSERT */
+
+	return m_loadValues[position*m_alphabetSize+symbol];
+}
+
+void Hypercube::makeConnections(int n){
+
+	configureGraph(n);
+
+	if(m_verbose){
+		cout<<"[Hypercube::makeConnections] using "<<m_wordLength<<" for diameter with base ";
+		cout<<m_alphabetSize<<endl;
+		cout<<"[Hypercube::makeConnections] The MPI graph has "<<m_size<<" vertices"<<endl;
+		cout<<"[Hypercube::makeConnections] The hypercube has "<<m_size<<" vertices"<<endl;
+	}
+
+	// create empty sets.
+	for(Rank i=0;i<m_size;i++){
+		set<Rank> b;
+		m_outcomingConnections.push_back(b);
+		m_incomingConnections.push_back(b);
+	}
+
+	// populate vertices
+	for(Rank i=0;i<m_size;i++){
+		Tuple a;
+		convertToVertex(i,&a);
+		m_graphToVertex.push_back(a);
+	}
+
+	// make all connections.
+	for(Rank i=0;i<m_size;i++){
+		for(Rank j=0;j<m_size;j++){
+			if(computeConnection(i,j)){
+				m_outcomingConnections[i].insert(j);
+				m_incomingConnections[j].insert(i);
+			}
+		}
+	}
+}
+
+/* 
+ * base m_alphabetSize to base 10 
+ * TODO: this should be moved upstream 
+ */
+int Hypercube::convertToBase10(Tuple*vertex){
+	int a=0;
+	for(int i=0;i<m_wordLength;i++){
+		a+=vertex->m_digits[i]*getPower(m_alphabetSize,i);
+	}
+	return a;
+}
+
+/**
+ * TODO: this should be moved upstream
+ */
+void Hypercube::printVertex(Tuple*a){
+	for(int i=0;i<m_wordLength;i++){
+		if(i!=0)
+			cout<<",";
+		int value=a->m_digits[i];
+		cout<<value;
+	}
+}
+
+/**
+ * TODO: remove me
+ */
+void Hypercube::computeRoute(Rank a,Rank b,vector<Rank>*route){}
+
+// use a round-robin algorithm.
+//#define __ROUND_ROBIN__
+Rank Hypercube::getNextRankInRoute(Rank source,Rank destination,Rank rank){
+
+	#ifdef __ROUND_ROBIN__
+
+	return computeNextRankInRouteWithRoundRobin(source,destination,rank);
+
+	#else
+
+	return computeNextRankInRoute(source,destination,rank);
+
+	#endif /* __ROUND_ROBIN__ */
+}
+
+/** with de Bruijn routing, no route are pre-computed at all */
+void Hypercube::makeRoutes(){
+	/* compute relay points */
+	computeRelayEvents();
+}
+
+/** to get the next rank,
+ * we need to shift the current one time on the left
+ * then, we find the maximum overlap
+ * between the current and the destination
+ *
+ * This value is the index of the digit in destination
+ * that we want to append to the next rank in the route
+ *
+ *	// example:
+	//
+	// base = 16
+	// digits = 3
+	//
+	// source = (0,4,2)
+	// destination = (9,8,7)
+	//
+	// the path is
+	//
+	// (0,4,2) -> (4,2,9) -> (2,9,8) -> (9,8,7)
+	//
+	// so for sure we have to shift the current by one on the left
+	//
+	// then the problem is how to choose which symbol to add 
+	//
+	// let's say that
+	//
+	// current = (4,2,9)
+	//
+	// then we should return (2,9,8) rapidly
+	//
+	// source=(0,2,2)
+	// destination=(2,2,1)
+	//
+	// (0,2,2) -> (2,2,1)	
+
+	// here we need to choose a digit from the destination
+	// and append it to the next
+	// case 1 destination can be obtained with 1 shift, overlap is 2
+	// case 2 destination can be obtained with 2 shifts, overlap is 1
+	// case 3 ...
+	// case m_digits destination can be obtained with m_digits shifts, overlap is 0
+
+ */
+Rank Hypercube::computeNextRankInRoute(Rank source,Rank destination,Rank current){
+
+	#ifdef ASSERT
+	assert(destination!=current); // we don't need any routing...
+	assert(source>=0);
+	assert(destination>=0);
+	assert(current>=0);
+	assert(source<m_size);
+	assert(destination<m_size);
+	assert(current<m_size);
+	#endif
+
+	//Tuple*sourceVertex=&(m_graphToVertex[source]);
+	Tuple*destinationVertex=&(m_graphToVertex[destination]);
+	Tuple*currentVertex=&(m_graphToVertex[current]);
+	
+	int NO_VALUE=-1;
+	int bestPosition=NO_VALUE;
+	int bestSymbol=NO_VALUE;
+	uint64_t bestLoad=NO_VALUE;
+
+	// select the next that has the lowest load.
+	for(int position=0;position<m_wordLength;position++){
+		//int sourceSymbol=sourceVertex[i];
+		int currentSymbol=currentVertex->m_digits[position];
+		int destinationSymbol=destinationVertex->m_digits[position];
+
+
+		// we don't need to test this one 
+		// because the bit is already correct
+		if(currentSymbol==destinationSymbol)
+			continue;
+	
+		// at this point, the symbol needs to be changed
+		uint64_t load=getLoad(position,destinationSymbol);
+
+		// select this edge if it has a lower load 
+		// or if it is the first one we are testing.
+		if(bestPosition==NO_VALUE||load<bestLoad){
+			bestPosition=position;
+			bestSymbol=destinationSymbol;
+			bestLoad=load;
+		}
+	}
+
+	// here, we know where we want to go
+	//
+	// This is the agenda:
+	//                 
+	//                  * we are here
+	//                  *
+	//                  *
+	// source -> ... -> current -> next -> ... -> destination
+
+	// we just need to update next with the choice having
+	// the lowest load
+
+	// the next will be populated in the loop
+	Tuple next=*currentVertex;
+
+
+	next.m_digits[bestPosition]=bestSymbol;
+	
+	// we increate the load by 1
+	setLoad(bestPosition,bestSymbol,bestLoad+1);
+
+	Rank nextRank=convertToBase10(&next);
+
+	#ifdef ASSERT
+	assert(current!=nextRank);
+	#endif
+
+	return nextRank;
+}
+
+/**
+ * TODO: move this upstream
+ */
+bool Hypercube::isConnected(Rank source,Rank destination){
+	if(source==destination)
+		return true;
+
+	return m_outcomingConnections[source].count(destination)==1;
+}
+
+/** 
+ * just verify the edge property
+ * also, we allow any vertex to communicate with itself
+ * regardless of the property
+ */
+bool Hypercube::computeConnection(Rank source,Rank destination){
+
+	if(source==destination) // no difference
+		return false;
+
+	// otherwise, we look for the de Bruijn property
+	Tuple*sourceVertex=&(m_graphToVertex[source]);
+	Tuple*destinationVertex=&(m_graphToVertex[destination]);
+
+	int differences=0;
+
+	for(int i=0;i<m_wordLength;i++){
+		if(sourceVertex->m_digits[i]!=destinationVertex->m_digits[i])
+			differences++;
+
+		if(differences>1) // more than 1 difference
+			return false;
+	}
+
+	return differences==1;
+}
+
+/**
+ * TODO: move this upstream, instead, add a protected m_valid field.
+ */
+bool Hypercube::isValid(int n){
+	configureGraph(n);
+
+	return m_alphabetSize!=__INVALID_ALPHABET_SIZE;
+}
+
+/**
+ * TODO: move this upstream
+ */
+void Hypercube::setDegree(int degree){
+	m_degree=degree;
+}
+
+void Hypercube::printStatus(Rank rank){
+	cout<<"[Hypercube] Load values:"<<endl;
+	cout<<"AlphabetSize: "<<m_alphabetSize<<endl;
+	cout<<"WordLength: "<<m_wordLength<<endl;
+	cout<<"Self: ";
+	Tuple*self=&(m_graphToVertex[rank]);
+
+	printVertex(self);
+	cout<<endl;
+
+	for(int i=0;i<m_wordLength;i++){
+
+		int selfSymbol=self->m_digits[i];
+
+		for(int j=0;j<m_alphabetSize;j++){
+
+			if(selfSymbol==j)// nothing to report
+				continue;
+
+			uint64_t load=getLoad(i,j);
+			Tuple copy=*self;
+			copy.m_digits[i]=j;
+			cout<<"  ";
+			printVertex(self);
+			cout<<" ("<<rank<<")";
+			cout<<" -> ";
+			printVertex(&copy);
+
+			Rank other=convertToBase10(&copy);
+			cout<<" ("<<other<<")";
+			cout<<" Load: "<<load<<endl;
+			
+		}
+	}
+}
+
+void Hypercube::start(){
+	for(int i=0;i<m_wordLength;i++)
+		for(int j=0;j<m_alphabetSize;j++)
+			setLoad(i,j,0);
+
+	m_currentPosition=0;
+	m_currentSymbol=0;
+}
+
+Rank Hypercube::computeNextRankInRouteWithRoundRobin(Rank source,Rank destination,Rank current){
+
+	#ifdef ASSERT
+	assert(destination!=current); // we don't need any routing...
+	assert(source>=0);
+	assert(destination>=0);
+	assert(current>=0);
+	assert(source<m_size);
+	assert(destination<m_size);
+	assert(current<m_size);
+	#endif
+
+	#ifdef ASSERT
+	Tuple*sourceVertex=&(m_graphToVertex[source]);
+	#endif
+
+	Tuple*destinationVertex=&(m_graphToVertex[destination]);
+	Tuple*currentVertex=&(m_graphToVertex[current]);
+	
+	int NO_VALUE=-1;
+	int bestPosition=NO_VALUE;
+	int bestSymbol=NO_VALUE;
+
+	#if 0 /* to disable round-robin */
+	m_currentPosition=0;
+	m_currentSymbol=0;
+	#endif
+
+
+	// first slice of round-robin
+	for(int position=m_currentPosition;position<m_wordLength;position++){
+
+		if(bestPosition!=NO_VALUE)// we found something
+			break;
+
+		int currentSymbol=currentVertex->m_digits[position];
+		int destinationSymbol=destinationVertex->m_digits[position];
+
+		if(destinationSymbol==currentSymbol)// it is already correct.
+			continue;
+
+		int symbolStart=0;
+
+		if(position==m_currentPosition)// for the first round, we start at m_currentSymbol
+			symbolStart=m_currentSymbol;
+
+		//symbolStart=0;// TODO: remove me
+
+		for(int symbol=symbolStart;symbol<m_alphabetSize;symbol++){
+
+			if(bestPosition!=NO_VALUE)// we found something
+				break;
+
+			if(symbol!=destinationSymbol)// this is not the correct symbol
+				continue;
+
+			// we found something to do!
+			bestPosition=position;
+			bestSymbol=symbol;
+		}
+
+	}
+
+	// second slice of round-robin
+	// we also try the symbols below m_currentSymbol for m_currentPosition
+	// to complete the round robin
+	for(int position=0;position<=m_currentPosition;position++){
+
+		if(bestPosition!=NO_VALUE)// we found something
+			break;
+
+		int currentSymbol=currentVertex->m_digits[position];
+		int destinationSymbol=destinationVertex->m_digits[position];
+
+		if(destinationSymbol==currentSymbol)// it is already correct.
+			continue;
+
+		int maximumSymbol=m_alphabetSize;
+
+		if(position==m_currentPosition)// we need to complete the round-robin
+			maximumSymbol=m_currentSymbol;
+
+		//maximumSymbol=m_alphabetSize;// TODO: remove me
+
+		for(int symbol=0;symbol<maximumSymbol;symbol++){
+
+			if(bestPosition!=NO_VALUE)// we found something
+				break;
+
+			if(symbol!=destinationSymbol)// this is not the correct symbol
+				continue;
+
+			// we found something to do!
+			bestPosition=position;
+			bestSymbol=symbol;
+		}
+
+	}
+
+	#ifdef ASSERT
+	if(bestPosition==NO_VALUE){
+		cout<<"Error: found no eligible position."<<endl;
+		cout<<"m_currentPosition: "<<m_currentPosition<<endl;
+		cout<<"m_currentSymbol: "<<m_currentSymbol<<endl;
+		cout<<"m_alphabetSize: "<<m_alphabetSize<<endl;
+		cout<<"m_wordLength: "<<m_wordLength<<endl;
+
+		cout<<"Source: "<<source<<" <=> ";
+		printVertex(sourceVertex);
+		cout<<endl;
+		cout<<"Current: "<<current<<" <=> ";
+		printVertex(currentVertex);
+		cout<<endl;
+		cout<<"Destination: "<<destination<<" <=> ";
+		printVertex(destinationVertex);
+		cout<<endl;
+	}
+	assert(bestPosition!=NO_VALUE);
+	assert(bestSymbol!=NO_VALUE);
+	#endif
+
+	// here, we know where we want to go
+	//
+	// This is the agenda:
+	//                 
+	//                  * we are here
+	//                  *
+	//                  *
+	// source -> ... -> current -> next -> ... -> destination
+
+	// we just need to update next with the choice having
+	// the lowest load
+
+	// the next will be populated in the loop
+	Tuple next=*currentVertex;
+
+	next.m_digits[bestPosition]=bestSymbol;
+	
+	uint64_t bestLoad=getLoad(bestPosition,bestSymbol);
+
+	// we increate the load by 1
+	setLoad(bestPosition,bestSymbol,bestLoad+1);
+
+	Rank nextRank=convertToBase10(&next);
+
+	#ifdef ASSERT
+	assert(current!=nextRank);
+	#endif
+
+	// update information for round-robin
+	
+	m_currentPosition=bestPosition;
+	m_currentSymbol=bestSymbol;
+	m_currentSymbol++;
+	if(m_currentSymbol==m_alphabetSize){
+		m_currentSymbol=0;
+		m_currentPosition++;
+	}
+	if(m_currentPosition==m_wordLength)
+		m_currentPosition=0;
+
+
+	return nextRank;
+}
diff --git a/RayPlatform/routing/Hypercube.h b/RayPlatform/routing/Hypercube.h
new file mode 100644
index 0000000..cbffeba
--- /dev/null
+++ b/RayPlatform/routing/Hypercube.h
@@ -0,0 +1,109 @@
+/*
+ 	RayPlatform
+    Copyright (C) 2010, 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _Hypercube_h
+#define _Hypercube_h
+
+#include <routing/GraphImplementation.h>
+#include <vector>
+#include <stdint.h>
+using namespace std;
+
+// for alphabetSize = 2 and 4096 vertices
+// we have 2^12 = 4096
+// each vertex has (2-1)*10 = 10 edges
+// in that case, the maximum index will be 12*2+11=35.
+//
+// for alphabetSize = 32
+// we have 32^2 =1024
+//
+// each vertex has (32-1)*2 = 62 edges
+// in that case, the maximum index will be 2*32+31=95
+//
+#define __NUMBER_OF_STORED_LOAD_VALUES 256
+
+/**
+ * Hypercube
+ * n must be a power of 2 to be a hypercube.
+ * Otherwise, it is an other polytope.
+ * A hypercube is a convex regular polytope.
+ * This class in fact implements a generalized hypercube,
+ * usually called a convex regular polytope.
+ * \author Sébastien Boisvert
+ */
+class Hypercube : public GraphImplementation{
+
+	uint64_t m_loadValues[__NUMBER_OF_STORED_LOAD_VALUES];
+
+	/** the user-provided degree */
+	int m_degree;
+
+	vector<Tuple> m_graphToVertex;
+
+	int m_alphabetSize;
+
+	int m_wordLength;
+
+	void configureGraph(int n);
+
+	int getPower(int base,int exponent);
+
+/** convert a number to a vertex */
+	void convertToVertex(int i,Tuple*tuple);
+
+/** convert a vertex to base 10 */
+	int convertToBase10(Tuple*vertex);
+
+	void printVertex(Tuple*a);
+	bool isAPowerOf(int n,int base);
+
+	int getMaximumOverlap(Tuple*a,Tuple*b);
+
+	Rank computeNextRankInRoute(Rank source,Rank destination,Rank rank);
+
+
+	Rank computeNextRankInRouteWithRoundRobin(Rank source,Rank destination,Rank rank);
+	int m_currentPosition;
+	int m_currentSymbol;
+	bool computeConnection(Rank source,Rank destination);
+
+
+	uint64_t getLoad(int position,int symbol);
+	void setLoad(int position,int symbol,uint64_t value);
+
+protected:
+
+	void computeRoute(Rank a,Rank b,vector<Rank>*route);
+	Rank getNextRankInRoute(Rank source,Rank destination,Rank rank);
+	bool isConnected(Rank source,Rank destination);
+public:
+
+	void makeConnections(int n);
+	void makeRoutes();
+
+	void setDegree(int degree);
+
+	bool isValid(int n);
+	void printStatus(Rank rank);
+	void start();
+};
+
+#endif
diff --git a/RayPlatform/scheduling/SwitchMan.cpp b/RayPlatform/scheduling/SwitchMan.cpp
new file mode 100644
index 0000000..9b4dfdd
--- /dev/null
+++ b/RayPlatform/scheduling/SwitchMan.cpp
@@ -0,0 +1,345 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#include <scheduling/SwitchMan.h>
+#include <assert.h>
+#include <vector>
+#include <core/OperatingSystem.h>
+#include <iostream>
+#include <core/ComputeCore.h>
+using namespace std;
+
+//#define CONFIG_SWITCHMAN_VERBOSITY
+
+__CreatePlugin(SwitchMan);
+
+__CreateMessageTagAdapter(SwitchMan,RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL);
+__CreateSlaveModeAdapter(SwitchMan,RAY_SLAVE_MODE_STOP);
+
+
+void SwitchMan::constructor(Rank rank,int numberOfCores){
+	m_rank=rank;
+	m_size=numberOfCores;
+	reset();
+
+	#ifdef ASSERT
+	runAssertions();
+	#endif
+
+}
+
+/** reset the sole counter */
+void SwitchMan::reset(){
+	m_counter=0;
+	#ifdef ASSERT
+	runAssertions();
+	#endif
+}
+
+bool SwitchMan::allRanksAreReady(){
+	#ifdef ASSERT
+	runAssertions();
+	#endif
+
+	return m_counter==m_size;
+}
+
+void SwitchMan::closeSlaveMode(Rank source){
+
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"[SwitchMan::closeSlaveMode] Closing remotely slave mode on rank "<<source<<endl;
+	#endif
+
+	m_counter++;
+
+	#ifdef ASSERT
+	runAssertions();
+	#endif
+}
+
+void SwitchMan::runAssertions(){
+	assert(m_counter<=m_size);
+	assert(m_counter>=0);
+}
+
+
+MasterMode SwitchMan::getNextMasterMode(MasterMode currentMode){
+	#ifdef ASSERT
+	if(m_switches.count(currentMode)==0){
+		cout<<"CurrentMode= "<<MASTER_MODES[currentMode]<<endl;
+	}
+
+	assert(m_switches.count(currentMode)>0);
+	#endif
+
+	if(m_switches.count(currentMode)==0)
+		cout<<"Error, there is no master mode after "<<MASTER_MODES[currentMode]<<endl;
+
+	return m_switches[currentMode];
+}
+
+void SwitchMan::addNextMasterMode(MasterMode a,MasterMode b){
+	#ifdef ASSERT
+	assert(m_switches.count(a)==0);
+	#endif
+
+	m_switches[a]=b;
+}
+
+void SwitchMan::openSlaveMode(MessageTag tag,StaticVector*outbox,Rank source,Rank destination){
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"[SwitchMan::openSlaveMode] Opening remotely slave mode on rank "<<destination<<endl;
+	#endif
+
+	#ifdef ASSERT
+	assert(source == MASTER_RANK); // only master can do that
+	#endif
+
+	sendMessage(NULL,0,outbox,source,destination,tag);
+}
+
+/** send a signal to the switchman */
+void SwitchMan::closeSlaveModeLocally(StaticVector*outbox,Rank source){
+
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"[SwitchMan::closeSlaveModeLocally] Closing locally slave mode on rank "<<source<<endl;
+	#endif
+
+	sendEmptyMessage(outbox,source,MASTER_RANK,RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL);
+
+	// set the slave mode to do nothing
+	// that is not productive...
+	setSlaveMode(RAY_SLAVE_MODE_DO_NOTHING);
+}
+
+void SwitchMan::openMasterMode(StaticVector*outbox,Rank source){
+
+	#ifdef ASSERT
+	if(m_masterModeToTagTable.count(m_masterMode)==0){
+		cout<<"Error, master mode is "<<MASTER_MODES[m_masterMode]<<endl;
+	}
+
+	assert(m_masterModeToTagTable.count(m_masterMode)>0);
+	#endif
+
+	MessageTag tag=m_masterModeToTagTable[m_masterMode];
+
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"[SwitchMan::openMasterMode] Opening master mode on rank "<<source<<endl;
+	cout<<"[SwitchMan::openMasterMode] tag= "<<MESSAGE_TAGS[tag]<<" source= "<<source<<" Outbox= "<<outbox<<endl;
+	#endif
+
+	#ifdef ASSERT
+	assert(source==MASTER_RANK);
+	assert(outbox!=NULL);
+	#endif
+
+	// open the slave mode on each MPI rank
+	for(Rank i=0;i<m_size;i++){
+		openSlaveMode(tag,outbox,source,i);
+	}
+
+	// reset the counter
+	reset();
+}
+
+void SwitchMan::closeMasterMode(){
+
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"[SwitchMan::closeMasterMode] Closing master mode on rank "<<MASTER_RANK<<endl;
+	#endif
+
+	// get the next master mode from the table
+	MasterMode currentMasterMode=getMasterMode();
+
+	if(currentMasterMode==RAY_MASTER_MODE_DO_NOTHING)
+		currentMasterMode=m_lastMasterMode;
+
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"[SwitchMan::closeMasterMode] Current master mode -> "<<MASTER_MODES[currentMasterMode]<<endl;
+	#endif
+
+	if(m_switches.count(currentMasterMode)==0)
+		return;
+
+	MasterMode nextMode=getNextMasterMode(currentMasterMode);
+
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"[SwitchMan::closeMasterMode] Next master mode -> "<<MASTER_MODES[nextMode]<<endl;
+	#endif
+
+	// set the new master mode
+	setMasterMode(nextMode);
+}
+
+void SwitchMan::sendEmptyMessage(StaticVector*outbox,Rank source,Rank destination,MessageTag tag){
+	sendMessage(NULL,0,outbox,source,destination,tag);
+}
+
+void SwitchMan::sendMessage(MessageUnit*buffer,int count,StaticVector*outbox,Rank source,Rank destination,MessageTag tag){
+	// send a message
+	Message aMessage(buffer,count,destination,tag,source);
+	outbox->push_back(aMessage);
+}
+
+void SwitchMan::sendToAll(StaticVector*outbox,Rank source,MessageTag tag){
+	sendMessageToAll(NULL,0,outbox,source,tag);
+}
+
+void SwitchMan::sendMessageToAll(MessageUnit*buffer,int count,StaticVector*outbox,Rank source,MessageTag tag){
+	for(int i=0;i<m_size;i++){
+		sendMessage(buffer,count,outbox,source,i,tag);
+	}
+}
+
+void SwitchMan::openSlaveModeLocally(MessageTag tag,Rank rank){
+	if(m_tagToSlaveModeTable.count(tag)==0)
+		return;
+
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"[SwitchMan::openSlaveModeLocally] Opening locally slave mode on rank "<<rank<<endl;
+	#endif
+
+	// translate the MPI tag to a slave mode 
+	SlaveMode desiredSlaveMode=m_tagToSlaveModeTable[tag];
+
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"[SwitchMan::openSlaveModeLocally] Slave switch triggered, Tag -> "<<MESSAGE_TAGS[tag]<<endl;
+	cout<<"[SwitchMan::openSlaveModeLocally] Slave mode -> "<<SLAVE_MODES[desiredSlaveMode]<<endl;
+	#endif
+
+	setSlaveMode(desiredSlaveMode);
+}
+
+void SwitchMan::addSlaveSwitch(MessageTag tag,SlaveMode slaveMode){
+	#ifdef ASSERT
+	assert(m_tagToSlaveModeTable.count(tag)==0);
+	#endif
+
+	m_tagToSlaveModeTable[tag]=slaveMode;
+}
+
+SlaveMode SwitchMan::getSlaveMode(){
+	return m_slaveMode;
+}
+
+int*SwitchMan::getSlaveModePointer(){
+	void*pointer=&m_slaveMode;
+	return (int*)pointer;
+}
+
+void SwitchMan::setSlaveMode(SlaveMode mode){
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"setSlaveMode "<<SLAVE_MODES[mode]<<endl;
+	#endif
+
+	m_slaveMode=mode;
+}
+
+MasterMode SwitchMan::getMasterMode(){
+	return m_masterMode;
+}
+
+void SwitchMan::setMasterMode(MasterMode mode){
+
+	#ifdef CONFIG_SWITCHMAN_VERBOSITY
+	cout<<"setMasterMode "<<MASTER_MODES[mode]<<endl;
+	#endif
+
+	m_masterMode=mode;
+
+	if(mode!=RAY_MASTER_MODE_DO_NOTHING)
+		m_lastMasterMode=mode;
+}
+
+int*SwitchMan::getMasterModePointer(){
+	void*pointer= &m_masterMode;
+	return(int*)pointer;
+}
+
+void SwitchMan::addMasterSwitch(MasterMode masterMode,MessageTag tag){
+	#ifdef ASSERT
+	assert(m_masterModeToTagTable.count(masterMode)==0);
+	#endif
+
+	m_masterModeToTagTable[masterMode]=tag;
+}
+
+Rank SwitchMan::getRank(){
+	return m_rank;
+}
+
+int SwitchMan::getSize(){
+	return m_size;
+}
+
+/* the switch man do the accounting for ready ranks */
+void SwitchMan::call_RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL(Message*message){
+	closeSlaveMode(message->getSource());
+}
+
+void SwitchMan::call_RAY_SLAVE_MODE_STOP(){
+
+	m_core->stop();
+
+	setSlaveMode(RAY_SLAVE_MODE_DO_NOTHING);
+}
+
+void SwitchMan::registerPlugin(ComputeCore*core){
+	m_plugin=core->allocatePluginHandle();
+
+	core->setPluginName(m_plugin,"SwitchMan");
+	core->setPluginDescription(m_plugin,"Parallel coordinator (bundled with RayPlatform)");
+	core->setPluginAuthors(m_plugin,"Sébastien Boisvert");
+	core->setPluginLicense(m_plugin,"GNU Lesser General License version 3");
+
+	RAY_SLAVE_MODE_DO_NOTHING=core->allocateSlaveModeHandle(m_plugin);
+	core->setSlaveModeSymbol(m_plugin,RAY_SLAVE_MODE_DO_NOTHING,"RAY_SLAVE_MODE_DO_NOTHING");
+
+	RAY_MASTER_MODE_DO_NOTHING=core->allocateMasterModeHandle(m_plugin);
+	core->setMasterModeSymbol(m_plugin,RAY_MASTER_MODE_DO_NOTHING,"RAY_MASTER_MODE_DO_NOTHING");
+
+	RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL=core->allocateMessageTagHandle(m_plugin);
+	core->setMessageTagObjectHandler(m_plugin,RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL,
+		__GetAdapter(SwitchMan,RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL));
+
+	core->setMessageTagSymbol(m_plugin,RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL,"RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL");
+
+	// set default modes
+	// these symbols are resolved already
+	
+	setMasterMode(RAY_MASTER_MODE_DO_NOTHING); 
+	setSlaveMode(RAY_SLAVE_MODE_DO_NOTHING);
+
+	m_core=core;
+}
+
+void SwitchMan::resolveSymbols(ComputeCore*core){
+	RAY_SLAVE_MODE_DO_NOTHING=core->getSlaveModeFromSymbol(m_plugin,"RAY_SLAVE_MODE_DO_NOTHING");
+
+	RAY_MASTER_MODE_DO_NOTHING=core->getMasterModeFromSymbol(m_plugin,"RAY_MASTER_MODE_DO_NOTHING");
+
+	RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL=core->getMessageTagFromSymbol(m_plugin,"RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL");
+
+	__BindPlugin(SwitchMan);
+}
+	
+
+
diff --git a/RayPlatform/scheduling/SwitchMan.h b/RayPlatform/scheduling/SwitchMan.h
new file mode 100644
index 0000000..e739e1c
--- /dev/null
+++ b/RayPlatform/scheduling/SwitchMan.h
@@ -0,0 +1,178 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011, 2012 Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _SwitchMan_H
+#define _SwitchMan_H
+
+#include <core/master_modes.h>
+#include <structures/StaticVector.h>
+#include <communication/Message.h>
+#include <core/slave_modes.h>
+#include <core/master_modes.h>
+#include <plugins/CorePlugin.h>
+#include <handlers/MessageTagHandler.h>
+#include <handlers/SlaveModeHandler.h>
+
+#include <map>
+#include <vector>
+using namespace std;
+
+class ComputeCore;
+class SwitchMan;
+
+/**
+ * the switchman controls the workflow on all ranks
+ * he is the one who decides when something must be done.
+ * \author Sébastien Boisvert
+ * \date 2012-01-02
+ */
+class SwitchMan: public CorePlugin {
+	
+	ComputeCore*m_core;
+
+	MessageTag RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL;
+
+	MasterMode RAY_MASTER_MODE_DO_NOTHING;
+	SlaveMode RAY_SLAVE_MODE_DO_NOTHING;
+	SlaveMode RAY_SLAVE_MODE_DIE;
+	SlaveMode RAY_SLAVE_MODE_STOP;
+
+/** the current slave mode of the rank */
+	SlaveMode m_slaveMode;
+
+/** the current master mode of the rank */
+	MasterMode m_masterMode;
+	
+	MasterMode m_lastMasterMode;
+
+/** the rank **/
+	Rank m_rank;
+
+	/** number of cores */
+	int m_size;
+
+/** a counter to check progression */
+	int m_counter;
+
+/** a list of switches describing the order of the master modes */
+	map<MasterMode,MasterMode> m_switches;
+
+/** a table to convert a tag to a slave mode */
+	map<MessageTag,SlaveMode> m_tagToSlaveModeTable;
+
+/** a table containing mapping from master modes to MPI tags */
+	map<MasterMode,MessageTag> m_masterModeToTagTable;
+
+/** run some assertions */
+	void runAssertions();
+
+public:
+
+/** the switchman is constructed with a number of cores */
+	void constructor(int rank,int numberOfRanks);
+
+/** reset */
+	void reset();
+
+/** returns true if all ranks finished their current slave mode */
+	bool allRanksAreReady();
+
+/** according to master_mode_order.txt, returns
+ * the next master mode to set */
+	MasterMode getNextMasterMode(MasterMode currentMode);
+
+/**
+ * add a master mode associated to another */
+	void addNextMasterMode(MasterMode a,MasterMode b);
+
+/** add a slave switch */
+	void addSlaveSwitch(MessageTag tag,SlaveMode slaveMode);
+
+/** add a master switch */
+	void addMasterSwitch(MasterMode masterMode,MessageTag tag);
+
+	/** remotely open a slave mode */
+	void openSlaveMode(MessageTag tag,StaticVector*outbox,Rank source,Rank destination);
+
+	/** open a slave mode locally */
+	void openSlaveModeLocally(MessageTag tag,Rank rank);
+
+	/** close a slave mode remotely */
+	void closeSlaveMode(Rank source);
+
+	/** locally close a slave mode */
+	void closeSlaveModeLocally(StaticVector*outbox,Rank source);
+
+	/** begin a master mode */
+	// TODO: add an option SERIAL or PARALLEL */
+	void openMasterMode(StaticVector*outbox,Rank source);
+
+	/** close a master mode */
+	void closeMasterMode();
+
+	/** send an empty message */
+	void sendEmptyMessage(StaticVector*outbox,Rank source,Rank destination,MessageTag tag);
+
+/** sends a message with a full list of parameters */
+	void sendMessage(MessageUnit*buffer,int count,StaticVector*outbox,Rank source,Rank destination,MessageTag tag);
+
+/** get the current slave mode */
+	SlaveMode getSlaveMode();
+
+/** get the current slave mode pointer */
+	int*getSlaveModePointer();
+
+/** change the slave mode manually */
+	void setSlaveMode(SlaveMode mode);
+
+/** get the master mode */
+	MasterMode getMasterMode();
+
+/** get the master mode pointer */
+	int*getMasterModePointer();
+
+/** changes the master mode manually */
+	void setMasterMode(MasterMode mode);
+
+/** send a message to all MPI ranks */
+	void sendToAll(StaticVector*outbox,Rank source,MessageTag tag);
+
+/** send a message to all MPI ranks, possibly with data */
+	void sendMessageToAll(MessageUnit*buffer,int count,StaticVector*outbox,Rank source,MessageTag tag);
+
+	void addMasterMode(MasterMode masterMode);
+
+	vector<MasterMode>*getMasterModeOrder();
+
+	Rank getRank();
+
+	int getSize();
+
+	void registerPlugin(ComputeCore*core);
+	void resolveSymbols(ComputeCore*core);
+
+	void addDummy(ComputeCore*core);
+
+	void call_RAY_MPI_TAG_SWITCHMAN_COMPLETION_SIGNAL(Message*message);
+
+	void call_RAY_SLAVE_MODE_STOP();
+};
+
+#endif
diff --git a/RayPlatform/scheduling/TaskCreator.cpp b/RayPlatform/scheduling/TaskCreator.cpp
new file mode 100644
index 0000000..923f350
--- /dev/null
+++ b/RayPlatform/scheduling/TaskCreator.cpp
@@ -0,0 +1,99 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#include <scheduling/TaskCreator.h>
+#include <stdlib.h> /* for NULL */
+
+#ifdef ASSERT
+#include <assert.h>
+#endif
+
+/* #define DEBUG_TASK_CREATOR */
+
+/** the main loop for a task creator */
+void TaskCreator::mainLoop(){
+	if(!m_initialized){
+		#ifdef DEBUG_TASK_CREATOR
+		cout<<"Initializing"<<endl;
+		#endif
+		initializeMethod();
+		m_initialized=true;
+		m_completedJobs=0;
+	}
+
+	if(hasUnassignedTask()){
+		if(m_virtualProcessor->canAddWorker()){
+			Worker*worker=assignNextTask();
+
+
+			#ifdef DEBUG_TASK_CREATOR
+			cout<<"Adding worker to pool worker= "<<worker<<" processor="<<m_virtualProcessor<<endl;
+			#endif
+
+			#ifdef ASSERT
+			assert(worker != NULL);
+			assert(m_virtualProcessor != NULL);
+			#endif
+
+			m_virtualProcessor->addWorker(worker);
+	
+			/* tell the VirtualProcessor that no more tasks will be created */
+			if(!hasUnassignedTask()){
+				#ifdef DEBUG_TASK_CREATOR
+				cout<<"No more task are coming."<<endl;
+				#endif
+				m_virtualProcessor->noMoreTasksAreComing();
+			}
+		}
+	}
+
+	Worker*worker=NULL;
+
+	bool aWorkerWorked=m_virtualProcessor->run();
+
+
+	if(aWorkerWorked){
+		worker=m_virtualProcessor->getCurrentWorker();
+	}
+
+	if(worker!=NULL && worker->isDone()){
+		#ifdef DEBUG_TASK_CREATOR
+		cout<<"Current worker is done"<<endl;
+		#endif
+		processWorkerResult(worker);
+		destroyWorker(worker);
+		m_completedJobs++;
+	}
+
+	if(!hasUnassignedTask() && !m_virtualProcessor->hasWorkToDo()){
+		finalizeMethod();
+
+		m_virtualProcessor->printStatistics();
+		m_virtualProcessor->reset();
+
+		#ifdef DEBUG_TASK_CREATOR
+		cout<<"calling finalizeMethod()"<<endl;
+		#endif
+
+	}
+}
+
+TaskCreator::~TaskCreator(){
+}
diff --git a/RayPlatform/scheduling/TaskCreator.h b/RayPlatform/scheduling/TaskCreator.h
new file mode 100644
index 0000000..469343c
--- /dev/null
+++ b/RayPlatform/scheduling/TaskCreator.h
@@ -0,0 +1,62 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _TaskCreator_H
+#define _TaskCreator_H
+
+#include <scheduling/Worker.h>
+#include <scheduling/VirtualProcessor.h>
+#include <memory/MyAllocator.h>
+
+/** this is an interface that should be implemented by child classes 
+ * m_initialized must be set to false in the child class
+ * */
+class TaskCreator{
+protected:
+	bool m_initialized;
+	VirtualProcessor*m_virtualProcessor;
+	uint64_t m_completedJobs;
+
+public:
+	/** main function */
+	void mainLoop();
+
+	/** initialize the whole thing */
+	virtual void initializeMethod() = 0;
+
+	/** finalize the whole thing */
+	virtual void finalizeMethod() = 0;
+
+	/** has an unassigned task left to compute */
+	virtual bool hasUnassignedTask() = 0;
+
+	/** assign the next task to a worker and return this worker */
+	virtual Worker*assignNextTask() = 0;
+
+	/** get the result of a worker */
+	virtual void processWorkerResult(Worker*worker) = 0;
+
+	/** destroy a worker */
+	virtual void destroyWorker(Worker*worker) = 0;
+
+	virtual ~TaskCreator();
+};
+
+#endif
diff --git a/RayPlatform/scheduling/VirtualProcessor.cpp b/RayPlatform/scheduling/VirtualProcessor.cpp
new file mode 100644
index 0000000..454e3c9
--- /dev/null
+++ b/RayPlatform/scheduling/VirtualProcessor.cpp
@@ -0,0 +1,258 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#include <scheduling/VirtualProcessor.h>
+#include <core/ComputeCore.h>
+
+#include <iostream>
+using namespace std;
+
+#ifdef ASSERT
+#include <assert.h>
+#endif
+
+/* #define DEBUG_VIRTUAL_PROCESSOR */
+
+void VirtualProcessor::updateStates(){
+	#ifdef DEBUG_VIRTUAL_PROCESSOR
+	cout<<"Removing "<<m_workersDone.size()<<" workers done."<<endl;
+	#endif
+
+	// erase completed jobs
+	for(int i=0;i<(int)m_workersDone.size();i++){
+		WorkerHandle workerId=m_workersDone[i];
+
+		#ifdef ASSERT
+		assert(m_activeWorkers.count(workerId)>0);
+		assert(m_aliveWorkers.count(workerId)>0);
+		#endif
+
+		m_activeWorkers.erase(workerId);
+		m_aliveWorkers.erase(workerId);
+
+		m_completedJobs++;
+	}
+	m_workersDone.clear();
+
+	#ifdef DEBUG_VIRTUAL_PROCESSOR
+	cout<<"Moving "<<m_waitingWorkers.size()<<" workers to sleep mode."<<endl;
+	#endif
+
+	/** make some worker sleep */
+	for(int i=0;i<(int)m_waitingWorkers.size();i++){
+		WorkerHandle workerId=m_waitingWorkers[i];
+
+		#ifdef ASSERT
+		assert(m_activeWorkers.count(workerId)>0);
+		#endif
+
+		m_activeWorkers.erase(workerId);
+	}
+	m_waitingWorkers.clear();
+
+	#ifdef DEBUG_VIRTUAL_PROCESSOR
+	cout<<"Moving "<<m_activeWorkersToRestore.size()<<" workers to active mode"<<endl;
+	#endif
+
+	/** wake up some workers */
+	for(int i=0;i<(int)m_activeWorkersToRestore.size();i++){
+		WorkerHandle workerId=m_activeWorkersToRestore[i];
+		m_activeWorkers.insert(workerId);
+	}
+
+	m_activeWorkersToRestore.clear();
+
+	m_virtualCommunicator->resetGlobalPushedMessageStatus();
+
+	#ifdef DEBUG_VIRTUAL_PROCESSOR
+	int activeWorkers=m_activeWorkers.size();
+	int aliveWorkers=m_aliveWorkers.size();
+	int sleepingWorkers=aliveWorkers-activeWorkers;
+	cout<<"VirtualProcessor statistics: active: "<<activeWorkers<<" sleeping: "<<sleepingWorkers<<" total: "<<aliveWorkers<<endl;
+	#endif
+}
+
+/** actually initialize the VirtualProcessor */
+void VirtualProcessor::constructor(StaticVector*outbox,StaticVector*inbox,RingAllocator*outboxAllocator,
+		VirtualCommunicator*vc){
+
+	#ifdef DEBUG_VIRTUAL_PROCESSOR
+	int rank=parameters->getRank();
+	cout<<"Rank "<<rank<<" Initializing VirtualProcessor"<<endl;
+	#endif
+
+	m_virtualCommunicator=vc;
+	m_inbox=inbox;
+	m_outboxAllocator=outboxAllocator;
+
+	/** the maximum number of workers on this VirtualProcessor */
+	m_maximumAliveWorkers=32768; /* 2**15 */
+
+	reset();
+}
+
+/** make the VirtualProcessor run a little bit */
+bool VirtualProcessor::run(){
+
+	if(!m_initiatedIterator){
+
+		m_activeWorkerIterator=m_activeWorkers.begin();
+		m_initiatedIterator=true;
+	}
+
+	/** fetch the message from the inbox and de-multiplex it if necessary */
+	m_virtualCommunicator->processInbox(&m_activeWorkersToRestore);
+
+	/** if the VirtualCommunicator is not ready, return immediately */
+	if(!m_virtualCommunicator->isReady()){
+		return false;
+	}
+
+	/** make the current worker work */
+	if(m_activeWorkerIterator!=m_activeWorkers.end()){
+		WorkerHandle workerId=*m_activeWorkerIterator;
+
+		/** save the current worker identifier */
+		m_currentWorker=workerId;
+
+		#ifdef ASSERT
+		if(m_aliveWorkers.count(workerId)==0){
+			cout<<"Error: "<<workerId<<" is not in alive workers "<<m_activeWorkers.size()<<endl;
+		}
+		assert(m_aliveWorkers.count(workerId)>0);
+		assert(!m_aliveWorkers[workerId]->isDone());
+		#endif
+		m_virtualCommunicator->resetLocalPushedMessageStatus();
+
+		/* make the worker work a little bit */
+		m_aliveWorkers[workerId]->work();
+
+		//force the worker to work until he finishes or pushes something on the stack
+		/*
+		while(!m_aliveWorkers[workerId]->isDone()&&!m_virtualCommunicator->getLocalPushedMessageStatus()){
+		}
+		*/
+
+		if(m_virtualCommunicator->getLocalPushedMessageStatus()){
+			m_waitingWorkers.push_back(workerId);
+		}else if(m_aliveWorkers[workerId]->isDone()){
+			m_workersDone.push_back(workerId);
+		} 
+
+		m_activeWorkerIterator++;
+
+		return true;
+	}else{
+		updateStates();
+
+		//  add one worker to active workers
+		//  reason is that those already in the pool don't communicate anymore -- 
+		//  as for they need responses.
+		if(!m_virtualCommunicator->getGlobalPushedMessageStatus() && m_activeWorkers.empty()){
+			/** if no more worker will be added, we need to forceFlush */
+
+			bool noMoreWorkerCanBeAdded=false;
+
+			/* we have a full array of idle workers */
+			if(!canAddWorker()){
+				noMoreWorkerCanBeAdded=true;
+			}
+
+			/* we have space to add further workers, but no workers will be added in the future */
+			if(canAddWorker() && !m_moreTasksAreComing){
+				noMoreWorkerCanBeAdded=true;
+			}
+
+			/* we have to force-flush something to get rid of these endless waiting */
+			if(noMoreWorkerCanBeAdded){
+				#ifdef DEBUG_VIRTUAL_PROCESSOR
+				cout<<"VirtualProcessor: calling forceFlush on VirtualCommunicator"<<endl;
+				#endif
+
+				m_virtualCommunicator->forceFlush();
+			}
+		}
+
+		m_activeWorkerIterator=m_activeWorkers.begin();
+
+		return false;
+	}
+
+	return false;
+}
+
+/** get the current worker */
+Worker*VirtualProcessor::getCurrentWorker(){
+	#ifdef ASSERT
+	assert(m_aliveWorkers.count(m_currentWorker) > 0);
+	#endif
+
+	return m_aliveWorkers[m_currentWorker];
+}
+
+/** can a worker be added ? */
+bool VirtualProcessor::canAddWorker(){
+	return (int)m_aliveWorkers.size() < m_maximumAliveWorkers;
+}
+
+/** add a worker */
+void VirtualProcessor::addWorker(Worker*worker){
+	#ifdef ASSERT
+	assert(worker != NULL);
+	#endif
+
+	WorkerHandle workerId=worker->getWorkerIdentifier();
+
+	#ifdef ASSERT
+	if(m_aliveWorkers.count(workerId)>0)
+		cout<<"Worker "<<workerId<<" already here"<<endl;
+	assert(m_aliveWorkers.count(workerId) == 0);
+	#endif
+
+	m_aliveWorkers[workerId]=worker;
+	m_activeWorkers.insert(workerId);
+
+	int population=m_aliveWorkers.size();
+	if(population>m_maximumWorkers){
+		m_maximumWorkers=population;
+	}
+}
+
+void VirtualProcessor::noMoreTasksAreComing(){
+	m_moreTasksAreComing=false;
+}
+
+void VirtualProcessor::reset(){
+	m_moreTasksAreComing=true;
+	m_initiatedIterator=false;
+	m_completedJobs=0;
+}
+
+bool VirtualProcessor::hasWorkToDo(){
+	return m_aliveWorkers.size()>0;
+}
+
+void VirtualProcessor::printStatistics(){
+	cout<<"VirtualProcessor: completed jobs: "<<m_completedJobs<<endl;
+
+	m_virtualCommunicator->printStatistics();
+}
+
+
diff --git a/RayPlatform/scheduling/VirtualProcessor.h b/RayPlatform/scheduling/VirtualProcessor.h
new file mode 100644
index 0000000..178af7e
--- /dev/null
+++ b/RayPlatform/scheduling/VirtualProcessor.h
@@ -0,0 +1,142 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _VirtualProcessor_h
+#define _VirtualProcessor_h
+
+#include <structures/StaticVector.h>
+#include <memory/RingAllocator.h>
+#include <scheduling/Worker.h>
+
+
+#include <set>
+#include <vector>
+using namespace std;
+
+/* workflow:
+
+design by Sébastien Boisvert
+2011-08-25
+
+Input:
+
+- array of tasks to perform
+- a VirtualCommunicator object (software)
+- a VirtualProcessor object (software)
+
+Output:
+
+- the result of all tasks
+
+
+pseudo code:
+
+
+work()
+
+	if has unassigned task to do
+		if virtualProcessor.canAddWorker
+			worker = worker given the said task (constructor)
+			virtualProcessor.addWorker(worker)
+
+			if this is the last task to do
+				virtualProcessor.noMoreTasksAreComing
+	}
+
+	virtualProcessor.run()
+	worker = virtualProcessor.getCurrentWorker
+
+	if worker.isDone
+		get the result of the worker
+		do something meaningful with the result
+		virtualProcessor.removeWorker(worker) (done automatically)
+		destroy the worker
+
+	if all tasks are finished
+		the is THE END
+
+*/
+
+
+/** an implementation of a VirtualProcessor
+ * It enables the sheduling of many workers on the same process.
+ * While some sleep, other work.
+ * Workers sleep when they wait for messages 
+ *
+ * \author Sébastien Boisvert
+*/
+class VirtualProcessor{
+
+	WorkerHandle m_currentWorker;
+
+	bool m_moreTasksAreComing;
+
+	bool m_initiatedIterator;
+	set<WorkerHandle> m_activeWorkers;
+	set<WorkerHandle>::iterator m_activeWorkerIterator;
+	int m_completedJobs;
+	int m_maximumAliveWorkers;
+	int m_maximumWorkers;
+	bool m_communicatorWasTriggered;
+	vector<WorkerHandle> m_workersDone;
+	vector<WorkerHandle> m_waitingWorkers;
+	vector<WorkerHandle> m_activeWorkersToRestore;
+
+	map<WorkerHandle,Worker*> m_aliveWorkers;
+
+	StaticVector*m_inbox;
+	StaticVector*m_outbox;
+	RingAllocator*m_outboxAllocator;
+	VirtualCommunicator*m_virtualCommunicator;
+
+	void updateStates();
+
+public:
+	/** actually initialize the VirtualProcessor */
+	void constructor(StaticVector*outbox,StaticVector*inbox,RingAllocator*outboxAllocator,
+		VirtualCommunicator*vc);
+
+	/** reset everything in the VirtualProcessor */
+	void reset();
+
+	/** make the VirtualProcessor run a little bit */
+	/** returns true if a worker worked */
+	bool run();
+
+	/** get the current worker */
+	Worker*getCurrentWorker();
+
+	/** can a worker be added ? */
+	bool canAddWorker();
+
+	/** add a worker */
+	void addWorker(Worker*worker);
+
+	/** no more task are coming */
+	void noMoreTasksAreComing();
+
+	/** returns true if some workers are alive */
+	bool hasWorkToDo();
+
+	void printStatistics();
+
+};
+
+#endif
diff --git a/RayPlatform/scheduling/Worker.h b/RayPlatform/scheduling/Worker.h
new file mode 100644
index 0000000..322586c
--- /dev/null
+++ b/RayPlatform/scheduling/Worker.h
@@ -0,0 +1,49 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _Worker_h
+#define _Worker_h
+
+#include <stdint.h>
+#include <memory/RingAllocator.h>
+#include <communication/VirtualCommunicator.h>
+
+/** a general worker class 
+ * \author Sébastien Boisvert
+ */
+class Worker{
+
+public:
+
+	/** work a little bit 
+	 * the class Worker provides no implementation for that 
+	*/
+	virtual void work() = 0;
+
+	/** is the worker done doing its things */
+	virtual bool isDone() = 0;
+
+	/** get the worker number */
+	virtual WorkerHandle getWorkerIdentifier() = 0 ;
+
+	virtual ~Worker(){}
+};
+
+#endif
diff --git a/RayPlatform/structures/MyHashTable.h b/RayPlatform/structures/MyHashTable.h
new file mode 100644
index 0000000..4302f24
--- /dev/null
+++ b/RayPlatform/structures/MyHashTable.h
@@ -0,0 +1,966 @@
+/*
+ 	Ray
+    Copyright (C) 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+/* the code in this file is based on my understanding (Sébastien Boisvert) of
+ * the content of this page about Google sparse hash map.
+ * \see http://google-sparsehash.googlecode.com/svn/trunk/doc/implementation.html
+ *
+ * 	double hashing is based on page 529 
+ * 	of 
+ * 	Donald E. Knuth
+ * 	The Art of Computer Programming, Volume 3, Second Edition
+ *
+ * Furthermore, it implements incremental resizing for real-time communication with low latency.
+ */
+
+#ifndef _MyHashTable_H
+#define _MyHashTable_H
+
+/**
+ * The precision of probe statistics.
+ */
+#define MAX_SAVED_PROBE 16
+
+#include <stdint.h>
+#include <time.h>
+#include "structures/MyHashTableGroup.h"
+#include <memory/ChunkAllocatorWithDefragmentation.h>
+#include <iostream>
+#include <assert.h>
+#include <string.h> /* for strcpy */
+#include <memory/allocator.h> /* for __Malloc */
+using namespace std;
+
+/**
+ * this hash table is specific to DNA
+ * uses open addressing with double hashing
+ *
+ * class KEY must have these methods:
+ *
+ * hash_function_1()
+ * hash_function_2()
+ * print()
+ *
+ * class VALUE must have these methods:
+ *
+ * getKey()
+ *
+ * the number of buckets can not be exceeded. 
+ * based on the description at
+ * \see http://google-sparsehash.googlecode.com/svn/trunk/doc/implementation.html
+ *
+ * all operations are constant-time or so.
+ *
+ * probing depth is usually low because incremental resizing is triggered at load >= 70.0%
+ * and double hashing eases exploration of bucket landscapes.
+ *
+ * \author Sébastien Boisvert
+ * \date 2012-08-07 This class was reviewed by David Weese <weese at campus.fu-berlin.de>
+ */
+template<class KEY,class VALUE>
+class MyHashTable{
+	/** is this table verbose */
+	bool m_verbose;
+
+	/** currently doing incremental resizing ? */
+	bool m_resizing;
+
+	/** auxiliary table for incremental resizing */
+	MyHashTable*m_auxiliaryTableForIncrementalResize;
+
+	/** current bucket to transfer */
+	uint64_t m_currentBucketToTransfer;
+
+/**
+ * the maximum acceptable load factor
+ * beyond that value, the table is resized.
+ */
+	double m_maximumLoadFactor;
+
+	/** 
+ * 	chunk allocator
+ */
+	ChunkAllocatorWithDefragmentation m_allocator;
+
+	/** 
+ * 	the  maximum probes required in probing
+ */
+	int m_probes[MAX_SAVED_PROBE];
+
+	/**
+ * Message-passing interface rank
+ */
+	int m_rank;
+
+	/**
+ * the number of buckets in the theater */
+	uint64_t m_totalNumberOfBuckets;
+
+	/**
+         * Number of utilised buckets 
+         */
+	uint64_t m_utilisedBuckets;
+
+/**
+ * 	number of inserted elements
+ * contains the sum of elements in the main table + the number of elements in the new
+ * table but not in the old one
+ * when not resizing, m_utilisedBuckets and m_size are the same
+ * when resizing, m_size may be larger than m_utilisedBuckets
+ */
+	uint64_t m_size;
+
+	/**
+ * 	groups of buckets
+ */
+	MyHashTableGroup<KEY,VALUE>*m_groups;
+
+	/**
+ * number of buckets per group
+ */
+	int m_numberOfBucketsInGroup;
+
+	/**
+ * 	number of groups 
+ */
+	int m_numberOfGroups;
+
+/**
+ * If the load factor is too high,
+ * double the size, and regrow everything in the new one.
+ */
+	void growIfNecessary();
+
+/**
+ * resize the hash table
+ */
+	void resize();
+
+/**
+ * the type of memory allocation 
+ */
+	char m_mallocType[100];
+
+/**
+ * show the allocation events ?
+ */
+	bool m_showMalloc;
+
+
+/*
+ * find a key, but specify if the auxiliary table should be searched also */
+	VALUE*findKey(KEY*key,bool checkAuxiliary);
+
+public:
+	
+	void toggleVerbosity();
+
+	/** unused constructor  */
+	MyHashTable();
+
+	/** unused constructor  */
+	~MyHashTable();
+
+	/**
+ * 	is the seat available
+ */
+	bool isAvailable(uint64_t a);
+
+	/**
+ * build the buckets and the hash */
+	void constructor(uint64_t buckets,const char*mallocType,bool showMalloc,int rank,
+		int bucketsPerGroup,double loadFactorThreshold);
+
+	/**
+ * find a seat given a key */
+	VALUE*find(KEY*key);
+
+	/**
+ * insert a key */
+	VALUE*insert(KEY*key);
+
+/**
+ * 	find a bucket given a key
+ * 	This uses double hashing for open addressing.
+ */
+	void findBucketWithKey(KEY*key,uint64_t*probe,int*group,int*bucketInGroup);
+
+	/**
+ * burn the theater */
+	void destructor();
+
+	/**
+ * 	get the number of occupied buckets 
+ */
+	uint64_t size();
+
+	/**
+ * 	get a bucket directly
+ * 	will fail if empty
+ */
+	VALUE*at(uint64_t a);
+	
+	/** get the number of buckets */
+	uint64_t capacity();
+
+	/**
+ * 	print the statistics of the hash table including,
+ * 	but not necessary limited to:
+ * 	- the load factor
+ */
+	void printStatistics();
+
+	void printProbeStatistics();
+
+/**
+ * callback function for immediate defragmentation
+ */
+	void defragment();
+
+	void completeResizing();
+
+	bool needsToCompleteResizing();
+};
+
+/* get a bucket */
+template<class KEY,class VALUE>
+VALUE*MyHashTable<KEY,VALUE>::at(uint64_t bucket){
+	int group=bucket/m_numberOfBucketsInGroup;
+	int bucketInGroup=bucket%m_numberOfBucketsInGroup;
+
+	#ifdef ASSERT
+	assert(m_groups[group].getBit(bucketInGroup)==1);
+	#endif
+
+	VALUE*e=m_groups[group].getBucket(bucketInGroup,&m_allocator);
+
+	return e;
+}
+
+/** returns the number of buckets */
+template<class KEY,class VALUE>
+uint64_t MyHashTable<KEY,VALUE>::capacity(){
+	return m_totalNumberOfBuckets;
+}
+
+/** makes the table grow if necessary */
+template<class KEY,class VALUE>
+void MyHashTable<KEY,VALUE>::growIfNecessary(){
+	if(m_resizing)
+		return;
+
+	/**  check if a growth is necessary */
+	double loadFactor=(0.0+m_utilisedBuckets)/m_totalNumberOfBuckets;
+	if(loadFactor<m_maximumLoadFactor)
+		return;
+
+	/** double the size */
+	uint64_t newSize=m_totalNumberOfBuckets*2;
+
+	/** nothing to do because shrinking is not implemented */
+	if(newSize<m_totalNumberOfBuckets)
+		return;
+
+	/** can not resize because newSize is too small */
+	/** this case actually never happens */
+	if(newSize<m_utilisedBuckets)
+		return;
+
+	m_currentBucketToTransfer=0;
+	m_resizing=true;
+
+	if(m_verbose){
+		cout<<"Beginning resizing operations"<<endl;
+		printProbeStatistics();
+	}
+
+	#ifdef ASSERT
+	assert(m_auxiliaryTableForIncrementalResize==NULL);
+	#endif
+
+	m_auxiliaryTableForIncrementalResize=new MyHashTable();
+
+	/** build a new larger table */
+	m_auxiliaryTableForIncrementalResize->constructor(newSize,m_mallocType,m_showMalloc,m_rank,
+		m_numberOfBucketsInGroup,m_maximumLoadFactor);
+
+	//cout<<"Rank "<<m_rank<<" MyHashTable must grow now "<<m_totalNumberOfBuckets<<" -> "<<newSize<<endl;
+	//printStatistics();
+
+	#ifdef ASSERT
+	assert(newSize>m_totalNumberOfBuckets);
+	#endif
+}
+
+/** 
+ * resize the whole hash table 
+ */
+template<class KEY,class VALUE>
+void MyHashTable<KEY,VALUE>::resize(){
+	#ifdef ASSERT
+	assert(m_resizing==true);
+	assert(m_utilisedBuckets>0);
+	#endif
+
+ /*
+ *	Suppose the main table has N slots.
+ *	Then, the auxiliary has 2*N slots.
+ *
+ *	At each call to insert(), we call resize().
+ *	Each call to resize() will transfert T items.
+ *
+ * 	In the worst case, the main table has exactly N items to transfert (all buckets are full).
+ * 	Thus, this would require N/T calls to resize()
+ *
+ * 	resize() is actually called when insert() is called, so
+ *	at completion of the transfer, the auxiliary table would have
+ *
+ *	N/T   (elements inserted directly in the auxiliary table)
+ *	N     (elements copied from the main table to the auxiliary table)
+ *
+ *	Thus, when the transfert is completed, the auxiliary table has 
+ *
+ *	at most N+N/T elements.
+ *
+ * 	We have 
+ *
+ * 	N+N/T <= 2N		(equation 1.)
+ * 	N+N/T -N  <= 2N -N
+ * 	N/T <= N
+ * 	N/T*1/N <= N * 1/N
+ * 	1/T <= 1
+ * 	1/T * T <= 1 * T
+ * 	1 <= T
+ *
+ * 	So,  basically, as long as T >= 1, we are fine.
+ *
+ * 	But in our case, resize is triggered when the main table has at least
+ * 	0.7*N
+ *
+ * 	So, we need 0.7*N/T calls to resizes.
+ *
+ * 	Upon completion, the auxiliary table will have
+ *
+ * 	0.7*N/T + 0.7*N
+ *
+ * 	The equation is then:
+ *
+ * 	0.7*N/T + 0.7*N <= 0.7*2*N 	equation 2.
+ *
+ * 	(we want the process to complete before auxiliary triggers its own incremental resizing !)
+ *
+ * 	(divide everything by 0.7)
+ *
+ * 	N/T+N<=2N
+ *
+ * 	(same equation as equation 1.)
+ *
+ * 	thus, T>=1
+ *
+ * 	Here, we choose T=2
+ * 	*/
+
+	int toProcess=2;
+
+	int i=0;
+	while(i<toProcess && m_currentBucketToTransfer<capacity()){
+		/** if the bucket is available, it means that it is empty */
+		if(!isAvailable(m_currentBucketToTransfer)){
+			VALUE*entry=at(m_currentBucketToTransfer);
+
+			#ifdef ASSERT
+			assert(entry!=NULL);
+			#endif
+
+			KEY keyValue=entry->getKey();
+			KEY*key=&keyValue;
+
+			#ifdef ASSERT
+			uint64_t probe;
+			int group;
+			int bucketInGroup;
+			findBucketWithKey(key,&probe,&group,&bucketInGroup);
+			uint64_t globalBucket=group*m_numberOfBucketsInGroup+bucketInGroup;
+			
+			if(globalBucket!=m_currentBucketToTransfer)
+				cout<<"Expected: "<<m_currentBucketToTransfer<<" Actual: "<<globalBucket<<endl;
+			assert(globalBucket==m_currentBucketToTransfer);
+
+			if(find(key)==NULL)
+				cout<<"Error: can not find the content of global bucket "<<m_currentBucketToTransfer<<endl;
+			assert(find(key)!=NULL);
+			#endif
+
+			/** remove the key too */
+			/* actually, can not remove anything because otherwise it will make the double hashing 
+ * 			fails */
+
+			/** save the size before for further use */
+			#ifdef ASSERT
+			uint64_t sizeBefore=m_auxiliaryTableForIncrementalResize->m_utilisedBuckets;
+
+			/* the auxiliary should not contain the key already . */
+			if(m_auxiliaryTableForIncrementalResize->find(key)!=NULL)
+				cout<<"Moving globalBucket "<<m_currentBucketToTransfer<<" but the associated key is already in auxiliary table."<<endl;
+			assert(m_auxiliaryTableForIncrementalResize->find(key)==NULL);
+			#endif
+
+			/* this pointer  will remain valid until the next insert. */
+			VALUE*insertedEntry=m_auxiliaryTableForIncrementalResize->insert(key);
+		
+			/** affect the value */
+			(*insertedEntry)=*entry;
+	
+			/** assert that we inserted something somewhere */
+			#ifdef ASSERT
+			if(m_auxiliaryTableForIncrementalResize->m_utilisedBuckets!=sizeBefore+1)
+				cout<<"Expected: "<<sizeBefore+1<<" Actual: "<<m_auxiliaryTableForIncrementalResize->m_utilisedBuckets<<endl;
+			assert(m_auxiliaryTableForIncrementalResize->m_utilisedBuckets==sizeBefore+1);
+			#endif
+		}
+		i++;
+		m_currentBucketToTransfer++;
+	}
+
+	/* we transfered everything */
+	if(m_currentBucketToTransfer==capacity()){
+		//cout<<"Rank "<<m_rank<<": MyHashTable incremental resizing is complete."<<endl;
+		/* make sure the old table is now empty */
+		#ifdef ASSERT
+		//assert(size()==0);
+		//the old table still has its stuff.
+		#endif
+
+		/** destroy the current table */
+		destructor();
+	
+		/** copy important stuff  */
+		m_groups=m_auxiliaryTableForIncrementalResize->m_groups;
+		m_totalNumberOfBuckets=m_auxiliaryTableForIncrementalResize->m_totalNumberOfBuckets;
+		m_allocator=m_auxiliaryTableForIncrementalResize->m_allocator;
+		m_numberOfGroups=m_auxiliaryTableForIncrementalResize->m_numberOfGroups;
+		m_utilisedBuckets=m_auxiliaryTableForIncrementalResize->m_utilisedBuckets;
+		m_size=m_auxiliaryTableForIncrementalResize->m_size;
+
+		#ifdef ASSERT
+		assert(m_size == m_utilisedBuckets);
+		assert(m_auxiliaryTableForIncrementalResize->m_resizing == false);
+		assert(m_size == m_utilisedBuckets);
+		#endif
+
+		/** copy probe profiles */
+		for(int i=0;i<MAX_SAVED_PROBE;i++)
+			m_probes[i]=m_auxiliaryTableForIncrementalResize->m_probes[i];
+	
+		/** indicates the caller that things changed places */
+
+		//printStatistics();
+		delete m_auxiliaryTableForIncrementalResize;
+		m_auxiliaryTableForIncrementalResize=NULL;
+		m_resizing=false;
+
+		if(m_verbose){
+			cout<<"Completed resizing operations"<<endl;
+			printProbeStatistics();
+		}
+	}
+}
+
+/** return the number of elements
+ * contains the number of elements in the main table + those in the second that are not in the first */
+template<class KEY,class VALUE>
+uint64_t MyHashTable<KEY,VALUE>::size(){
+	return m_size;
+}
+
+
+template<class KEY,class VALUE>
+void MyHashTable<KEY,VALUE>::toggleVerbosity(){
+	m_verbose=!m_verbose;
+}
+
+/** build the hash table given a number of buckets 
+ * this is private actually 
+ * */
+template<class KEY,class VALUE>
+void MyHashTable<KEY,VALUE>::constructor(uint64_t buckets,const char*mallocType,bool showMalloc,int rank,
+	int bucketsPerGroup,double loadFactorThreshold){
+
+	// adjust the buckets.
+	uint64_t check=2;
+	while(check<buckets)
+		check*=2;
+	
+	if(check!=buckets){
+		cout<<"Warning: the number of buckets must be a power of 2"<<endl;
+		buckets=check;
+		cout<<"Changed buckets to "<<buckets<<endl;
+	}
+
+	/** this is the maximum acceptable load factor. */
+	/** based on Figure 42 on page 531 of
+ * 	The Art of Computer Programming, Second Edition, by Donald E. Knuth
+ */
+
+	/* TODO: why does the code crash when loadFactorThreshold < 0.5 ? */
+	/* probably has something to do with resizing */
+	if(loadFactorThreshold<0.5)
+		loadFactorThreshold=0.5;
+
+	if(loadFactorThreshold>1)
+		loadFactorThreshold=1;
+
+	m_maximumLoadFactor=loadFactorThreshold; 
+	m_numberOfBucketsInGroup=bucketsPerGroup;
+
+	m_auxiliaryTableForIncrementalResize=NULL;
+	m_resizing=false;
+
+	/** set the message-passing interface rank number */
+	m_rank=rank;
+
+	m_verbose=false;
+	
+	m_allocator.constructor(sizeof(VALUE),showMalloc);
+	strcpy(m_mallocType,mallocType);
+
+	m_showMalloc=showMalloc;
+
+	/* use the provided number of buckets */
+	/* the number of buckets is a power of 2 */
+	m_totalNumberOfBuckets=buckets;
+
+	m_size=0;
+
+	m_utilisedBuckets=0;
+
+	/* the number of buckets in a group
+ * 	this is arbitrary I believe... 
+ * 	in my case, 64 is the number of bits in a uint64_t
+ * 	*/
+	m_numberOfBucketsInGroup=bucketsPerGroup;
+
+	/**
+ * 	compute the required number of groups 
+ */
+	m_numberOfGroups=(m_totalNumberOfBuckets-1)/m_numberOfBucketsInGroup+1;
+
+	/**
+ * 	Compute the required number of bytes
+ */
+	int requiredBytes=m_numberOfGroups*sizeof(MyHashTableGroup<KEY,VALUE>);
+
+	/** sanity check */
+	#ifdef ASSERT
+	if(requiredBytes<=0)
+		cout<<"Groups="<<m_numberOfGroups<<" RequiredBytes="<<requiredBytes<<"  BucketsPower2: "<<m_totalNumberOfBuckets<<endl;
+	assert(requiredBytes>=0);
+	#endif
+
+	/** allocate groups */
+	m_groups=(MyHashTableGroup<KEY,VALUE>*)__Malloc(requiredBytes,
+		mallocType,showMalloc);
+
+	#ifdef ASSERT
+	assert(m_groups!=NULL);
+	#endif
+
+	/** initialize groups */
+	for(int i=0;i<m_numberOfGroups;i++)
+		m_groups[i].constructor(m_numberOfBucketsInGroup,&m_allocator);
+
+	/*  set probe profiles to 0 */
+	for(int i=0;i<MAX_SAVED_PROBE;i++)
+		m_probes[i]=0;
+}
+
+/** return yes if the bucket is empty, no otherwise */
+template<class KEY,class VALUE>
+bool MyHashTable<KEY,VALUE>::isAvailable(uint64_t bucket){
+	int group=bucket/m_numberOfBucketsInGroup;
+	int bucketInGroup=bucket%m_numberOfBucketsInGroup;
+	
+	#ifdef ASSERT
+	assert(bucket<m_totalNumberOfBuckets);
+	assert(group<m_numberOfGroups);
+	assert(bucketInGroup<m_numberOfBucketsInGroup);
+	#endif
+
+	return m_groups[group].getBit(bucketInGroup)==0;
+}
+
+/** empty constructor, I use constructor instead  */
+template<class KEY,class VALUE>
+MyHashTable<KEY,VALUE>::MyHashTable(){}
+
+/** empty destructor */
+template<class KEY,class VALUE>
+MyHashTable<KEY,VALUE>::~MyHashTable(){}
+
+/**
+ * find a bucket
+ *
+ * using probing, assuming a number of buckets that is a power of 2 
+ * "But what is probing ?", you may ask.
+ * This stuff is pretty simple actually.
+ * Given an array of N elements and a key x and an hash
+ * function HASH_FUNCTION, one simple way to get the bucket is
+ *
+ *  bucket =   HASH_FUNCTION(x)%N
+ *
+ * If a collision occurs (another key already uses bucket),
+ * probing allows one to probe another bucket.
+ *
+ *  bucket =   ( HASH_FUNCTION(x) + probe(i) )%N
+ *          
+ *             where i is initially 0
+ *             when there is a collision, increment i and check the new  bucket
+ *             repeat until satisfied.
+ */
+template<class KEY,class VALUE>
+void MyHashTable<KEY,VALUE>::findBucketWithKey(KEY*key,uint64_t*probe,int*group,int*bucketInGroup){
+	/** 
+ * 	double hashing is based on 
+ * 	page 529 
+ * 	of 
+ * 	Donald E. Knuth
+ * 	The Art of Computer Programming, Volume 3, Second Edition
+ */
+	(*probe)=0; 
+
+	/** between 0 and M-1 -- M is m_totalNumberOfBuckets */
+	uint64_t h1=key->hash_function_2()%m_totalNumberOfBuckets;
+
+	/* first probe is 0 */
+	/** double hashing is computed on probe 1, not on 0 */
+	uint64_t h2=0;
+	uint64_t bucket=0;
+
+	bucket=(h1+(*probe)*h2)%m_totalNumberOfBuckets;
+
+	/** use double hashing */
+	(*group)=bucket/m_numberOfBucketsInGroup;
+	(*bucketInGroup)=bucket%m_numberOfBucketsInGroup;
+
+	#ifdef ASSERT
+	assert(bucket<m_totalNumberOfBuckets);
+	assert(*group<m_numberOfGroups);
+	assert(*bucketInGroup<m_numberOfBucketsInGroup);
+	#endif
+
+	/** probe bucket */
+	while(m_groups[*group].bucketIsUtilisedBySomeoneElse(*bucketInGroup,key,&m_allocator)
+		&& ((*probe)+1) < m_totalNumberOfBuckets){
+
+		(*probe)++;
+		
+		/** the stride and the number of buckets are relatively prime because
+			number of buckets = M = 2^m
+		and the stride is 1 <= s <= M-1 and is odd thus does not share factor with 2^m */
+
+		#ifdef ASSERT
+		/** issue a warning for an unexpected large probe depth */
+		/** each bucket should be probed in exactly NumberOfBuckets probing events */
+		if((*probe)>=m_totalNumberOfBuckets){
+			cout<<"Rank "<<m_rank<<" Warning, probe depth is "<<(*probe)<<" h1="<<h1<<" h2="<<h2<<" m_totalNumberOfBuckets="<<m_totalNumberOfBuckets<<" m_size="<<m_size<<" m_utilisedBuckets="<<m_utilisedBuckets<<" bucket="<<bucket<<" m_resizing="<<m_resizing<<endl;
+		}
+
+		assert((*probe)<m_totalNumberOfBuckets);
+		#endif
+
+		/** only compute the double hashing once */
+		if((*probe)==1){
+			/**  page 529 
+ * 				between 1 and M-1 exclusive
+				odd number
+ * 			*/
+
+			h2=key->hash_function_1()%m_totalNumberOfBuckets;
+			
+			/** h2 can not be 0 */
+			if(h2 == 0)
+				h2=1;
+
+			/** h2 can not be even */
+			if(h2%2 == 0)
+				h2--; 
+
+			/** check boundaries */
+			#ifdef ASSERT
+			assert(h2!=0);
+			assert(h2%2!=0);
+			assert(h2%2 == 1);
+			assert(h2>=1);
+
+/*
+			if(h2>=m_totalNumberOfBuckets)
+				cout<<"h2= "<<h2<<" Buckets= "<<m_totalNumberOfBuckets<<endl;
+*/
+			assert(h2<m_totalNumberOfBuckets);
+			assert((*probe)<m_totalNumberOfBuckets);
+			#endif
+		}
+
+		#ifdef ASSERT
+		assert(h2!=0);
+		#endif
+		
+		/** use double hashing */
+		//bucket=(h1+(*probe)*h2)%m_totalNumberOfBuckets;
+		
+		if(h2>bucket)
+			bucket+=m_totalNumberOfBuckets;
+
+		bucket-=h2;
+
+		(*group)=bucket/m_numberOfBucketsInGroup;
+		(*bucketInGroup)=bucket%m_numberOfBucketsInGroup;
+
+		/** sanity checks */
+		#ifdef ASSERT
+		assert(bucket<m_totalNumberOfBuckets);
+		assert(*group<m_numberOfGroups);
+		assert(*bucketInGroup<m_numberOfBucketsInGroup);
+		#endif
+	}
+
+	/** sanity checks */
+	#ifdef ASSERT
+	assert(bucket<m_totalNumberOfBuckets);
+	assert(*group<m_numberOfGroups);
+	assert(*bucketInGroup<m_numberOfBucketsInGroup);
+	#endif
+}
+
+/**
+ * finds a key
+ */
+template<class KEY,class VALUE>
+VALUE*MyHashTable<KEY,VALUE>::findKey(KEY*key,bool checkAuxiliary){ /* for verbosity */
+
+	if(m_resizing && checkAuxiliary){
+		/* check the new one first */
+		VALUE*result=m_auxiliaryTableForIncrementalResize->find(key);
+		if(result!=NULL)
+			return result;
+	}
+
+	/** get the bucket */
+	uint64_t probe;
+	int group;
+	int bucketInGroup;
+	findBucketWithKey(key,&probe,&group,&bucketInGroup);
+
+	#ifdef ASSERT
+	assert(group<m_numberOfGroups);
+	assert(bucketInGroup<m_numberOfBucketsInGroup);
+	#endif
+	
+	#if 0
+	if(m_verbose){
+		cout<<"GridTable (service provided by MyHashTable) -> found key [";
+		for(int i=0;i<key->getNumberOfU64();i++){
+			if(i>0)
+				cout<<" ";
+
+			cout<<hex<<""<<key->getU64(i)<<dec;
+		}
+		cout<<"] on rank "<<m_rank;
+		cout<<" in group "<<group<<" in bucket "<<bucketInGroup;
+		cout<<" after "<<probe<<" probe operation";
+		if(probe>1)
+			cout<<"s";
+		cout<<endl;
+	}
+	#endif
+
+	/** ask the group to find the key */
+	return m_groups[group].find(bucketInGroup,key,&m_allocator);
+}
+
+/**
+ * finds a key
+ */
+template<class KEY,class VALUE>
+VALUE*MyHashTable<KEY,VALUE>::find(KEY*key){
+	#ifdef ASSERT
+	assert(key!=NULL);
+	#endif
+
+	return findKey(key,true);
+}
+
+/**
+ * inserts a key
+ * \author Sébastien Boisvert
+ * \date 2012-08-07 This method was reviewed by David Weese <weese at campus.fu-berlin.de>
+ */
+template<class KEY,class VALUE>
+VALUE*MyHashTable<KEY,VALUE>::insert(KEY*key){
+	/** do incremental resizing */
+	if(m_resizing){
+		resize();
+	}
+
+	if(m_resizing){ // the auxiliary table is only alive during resizing operations
+
+		// Case 1. If a key is already in the new one, then the new one is 
+		// responsible, regardless if it was in the old one or not 
+
+		VALUE*fromAuxiliary=m_auxiliaryTableForIncrementalResize->findKey(key,false);
+
+		if(fromAuxiliary!=NULL){
+			return fromAuxiliary;
+		}
+
+		// Case 2. If a key if not in the old (and was never in the old one), 
+		// then the new one is responsible for it 
+		//
+		/* check if key is not in the main table
+ 		 * 		insert it in the other one */
+		if(findKey(key,false)==NULL){
+			uint64_t sizeBefore=m_auxiliaryTableForIncrementalResize->m_utilisedBuckets;
+			VALUE*e=m_auxiliaryTableForIncrementalResize->insert(key);
+			if(m_auxiliaryTableForIncrementalResize->m_utilisedBuckets>sizeBefore){
+				m_size++;
+			}
+			return e;
+		}
+	}
+
+	// Case 3. Otherwise, the old one is responsible. 
+	//
+	
+	#ifdef ASSERT
+	uint64_t beforeSize=m_utilisedBuckets;
+	#endif
+
+	/** find the group */
+	uint64_t probe;
+	int group;
+	int bucketInGroup;
+	findBucketWithKey(key,&probe,&group,&bucketInGroup);
+
+	#ifdef ASSERT
+	assert(group<m_numberOfGroups);
+	assert(bucketInGroup<m_numberOfBucketsInGroup);
+	#endif
+
+	/* actually insert something somewhere */
+	bool inserted=false;
+	VALUE*entry=m_groups[group].insert(m_numberOfBucketsInGroup,bucketInGroup,key,&m_allocator,&inserted);
+
+	/* check that nothing failed elsewhere */
+	#ifdef ASSERT
+	assert(entry!=NULL);
+	if(entry->getKey()!=*key)
+		cout<<"Pointer: "<<entry<<endl;
+	assert(entry->getKey()==*key);
+	assert(m_groups[group].find(bucketInGroup,key,&m_allocator)!=NULL);
+	assert(m_groups[group].find(bucketInGroup,key,&m_allocator)->getKey()==*key);
+	#endif
+
+	/* increment the elements if an insertion occured */
+	if(inserted){
+		m_utilisedBuckets++;
+		m_size++;
+		/* update the maximum number of probes */
+		if(probe>(MAX_SAVED_PROBE-1))
+			probe=(MAX_SAVED_PROBE-1);
+		m_probes[probe]++;
+	}
+
+	#ifdef ASSERT
+	assert(find(key)!=NULL);
+	assert(find(key)->getKey()==*key);
+	if(inserted)
+		assert(m_utilisedBuckets==beforeSize+1);
+	#endif
+
+
+	/* check the load factor */
+	growIfNecessary();
+	
+	return entry;
+}
+
+/** destroy the hash table */
+template<class KEY,class VALUE>
+void MyHashTable<KEY,VALUE>::destructor(){
+	m_allocator.destructor();
+	__Free(m_groups,m_mallocType,m_showMalloc);
+}
+
+/**
+ * print handy statistics 
+ */
+template<class KEY,class VALUE>
+void MyHashTable<KEY,VALUE>::printStatistics(){
+	//m_allocator.print();
+}
+
+template<class KEY,class VALUE>
+void MyHashTable<KEY,VALUE>::printProbeStatistics(){
+
+	if(!m_verbose)
+		return; /**/
+
+	double loadFactor=(0.0+m_utilisedBuckets)/m_totalNumberOfBuckets*100;
+	cout<<"Rank "<<m_rank<<": MyHashTable, BucketGroups: "<<m_numberOfGroups<<", BucketsPerGroup: "<<m_numberOfBucketsInGroup<<", LoadFactor: "<<loadFactor<<"%, OccupiedBuckets: "<<m_utilisedBuckets<<"/"<<m_totalNumberOfBuckets<<endl;
+	cout<<"Rank "<<m_rank<<": incremental resizing in progress: ";
+	if(m_resizing)
+		cout<<"yes";
+	else
+		cout<<"no";
+	cout<<endl;
+
+	cout<<"Rank "<<m_rank<<" ProbeStatistics: ";
+	for(int i=0;i<MAX_SAVED_PROBE;i++){
+		if(m_probes[i]!=0)
+			cout<<" "<<i<<" -> "<<m_probes[i]<<"";
+	}
+
+	cout<<endl;
+
+	cout<<"Memory usage"<<endl;
+
+	m_allocator.print();
+}
+
+template<class KEY,class VALUE>
+void MyHashTable<KEY,VALUE>::completeResizing(){
+	while(m_resizing)
+		resize();
+
+	#ifdef ASSERT
+	assert(m_auxiliaryTableForIncrementalResize == NULL);
+	#endif
+
+	if(m_verbose)
+		printProbeStatistics();
+}
+
+template<class KEY,class VALUE>
+bool MyHashTable<KEY,VALUE>::needsToCompleteResizing(){
+	return m_resizing;
+}
+
+#endif
diff --git a/RayPlatform/structures/MyHashTableGroup.h b/RayPlatform/structures/MyHashTableGroup.h
new file mode 100644
index 0000000..62dd2aa
--- /dev/null
+++ b/RayPlatform/structures/MyHashTableGroup.h
@@ -0,0 +1,463 @@
+/*
+ 	Ray
+    Copyright (C) 2011, 2012  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _MyHashTableGroup_hh
+#define _MyHashTableGroup_hh
+
+#include <stdint.h>
+#include <time.h>
+#include <memory/ChunkAllocatorWithDefragmentation.h>
+#include <iostream>
+#include <assert.h>
+using namespace std;
+
+/* debug the hardware stuff (gcc built-ins */
+//#define __hardware_debugging_gnuc
+
+
+/**
+ * This is an hash group.
+ * MyHashTable contains many MyHashTableGroup.
+ * Each MyHashTableGroup is responsible for a slice of buckets.
+ * \see http://google-sparsehash.googlecode.com/svn/trunk/doc/implementation.html
+ *
+ * All operations are constant-time or so
+ * \author Sébastien Boisvert
+ * \date 2012-08-07 This class was reviewed by David Weese <weese at campus.fu-berlin.de>
+ */
+template<class KEY,class VALUE>
+class MyHashTableGroup{
+
+	#ifdef __hardware_debugging_gnuc
+
+	void __hash_print64(uint64_t a);
+
+	#endif /* __hardware_debugging_gnuc */
+
+
+
+	/**
+ * 	The VALUEs
+ */
+	SmartPointer m_vector;
+
+	/**
+ * 	the bitmap containing the presence of absence  of a bucket 
+ */
+	uint64_t m_bitmap;
+
+	/**
+ * 	set a bit
+ */
+	void setBit(int i,uint64_t j);
+public:
+	void print(ChunkAllocatorWithDefragmentation*allocator,int numberOfBucketsInGroup);
+
+	/** requests the bucket directly
+ * 	fails if it is empty
+ * 	*/
+	VALUE*getBucket(int bucket,ChunkAllocatorWithDefragmentation*a);
+
+/**
+ * get the number of occupied buckets before bucket 
+ */
+	int getBucketsBefore(int bucket);
+
+	int getUsedBuckets();
+
+	int __countBits(uint64_t value);
+
+	/**
+ * 	is the bucket utilised by someone else than key ?
+ */
+	bool bucketIsUtilisedBySomeoneElse(int bucket,KEY*key,ChunkAllocatorWithDefragmentation*allocator);
+
+	/**
+ * 	get the bit
+ */
+	int getBit(int i);
+
+	/** 
+ * 	build a group of buckets
+ */
+	void constructor(int numberOfBucketsInGroup,ChunkAllocatorWithDefragmentation*allocator);
+
+	/**
+ * 	insert into the group
+ * 	should not be called if the bucket is used by someone else already
+ * 	otherwise it *will* fail
+ */
+	VALUE*insert(int numberOfBucketsInGroup,int bucket,KEY*key,ChunkAllocatorWithDefragmentation*allocator,bool*inserted);
+
+	/**
+ * 	find a key
+ * 	should not be called if the bucket is used by someone else already
+ * 	otherwise it *will* fail
+ */
+	VALUE*find(int bucket,KEY*key,ChunkAllocatorWithDefragmentation*allocator);
+
+};
+
+/** sets the bit in the correct byte */
+template<class KEY,class VALUE>
+void MyHashTableGroup<KEY,VALUE>::setBit(int bit,uint64_t value){
+/**
+ * 	just set the bit to value in m_bitmap
+ */
+	#ifdef ASSERT
+	assert(value==1||value==0);
+	#endif
+	
+	/** use binary and or binary or */
+
+	/* set bit to 1 */
+	if(value==1){
+		m_bitmap|=(value<<bit);
+
+	/* set bit to 0 */
+	}else if(value==0){
+		uint64_t filter=1;
+		filter<<=bit;
+		filter=~filter;
+		m_bitmap&=filter;
+	}
+
+	/** make sure the bit is OK */
+	#ifdef ASSERT
+	if(getBit(bit)!=(int)value)
+		cout<<"Bit="<<bit<<" Expected="<<value<<" Actual="<<getBit(bit)<<endl;
+	assert(getBit(bit)==(int)value);
+	#endif
+}
+
+/* replace  hard-coded 64 by m_numberOfBucketsInGroup  or numberOfBucketsInGroup 
+ * 2012-08-07 - done */
+template<class KEY,class VALUE>
+void MyHashTableGroup<KEY,VALUE>::print(ChunkAllocatorWithDefragmentation*allocator,int
+	numberOfBucketsInGroup){
+
+	cout<<"Group bitmap"<<endl;
+	for(int i=0;i<numberOfBucketsInGroup;i++)
+		cout<<" "<<i<<":"<<getBit(i);
+	cout<<endl;
+}
+
+/** gets the bit  */
+template<class KEY,class VALUE>
+int MyHashTableGroup<KEY,VALUE>::getBit(int bit){
+	/* use a uint64_t word because otherwise bits are not correct */
+	int bitValue=(m_bitmap<<(63-bit))>>63;
+
+	/**  just a sanity check here */
+	#ifdef ASSERT
+	assert(bitValue==0||bitValue==1);
+	#endif
+
+	return bitValue;
+}
+
+/** builds the group of buckets */
+template<class KEY,class VALUE>
+void MyHashTableGroup<KEY,VALUE>::constructor(int numberOfBucketsInGroup,ChunkAllocatorWithDefragmentation*allocator){
+	/** we start with an empty m_vector */
+	m_vector=SmartPointer_NULL;
+
+	/* the number of buckets in a group must be a multiple of 8 */
+	/* why ? => to save memory -- not to waste memory */
+	#ifdef ASSERT
+	//assert(numberOfBucketsInGroup%8==0);
+	// this is not necessary.
+	#endif
+
+	/** set all bits to 0 */
+	m_bitmap=0;
+}
+
+/**
+ * inserts a key in a group
+ * if the bucket is already utilised, then its key is key
+ * if it is not used, key is added in bucket.
+ */
+template<class KEY,class VALUE>
+VALUE*MyHashTableGroup<KEY,VALUE>::insert(int numberOfBucketsInGroup,int bucket,KEY*key,
+	ChunkAllocatorWithDefragmentation*allocator,bool*inserted){
+
+	/* the bucket can not be used by another key than key */
+	/* if it would be the case, then MyHashTable would not have sent key here */
+	#ifdef ASSERT
+	if(bucketIsUtilisedBySomeoneElse(bucket,key,allocator)){
+		cout<<"Error, bucket "<<bucket<<" is utilised by another key numberOfBucketsInGroup "<<numberOfBucketsInGroup<<" utilised buckets in group: "<<getUsedBuckets()<<endl;
+	}
+	assert(!bucketIsUtilisedBySomeoneElse(bucket,key,allocator));
+	#endif
+
+	/*  count the number of occupied buckets before bucket */
+	int bucketsBefore=getBucketsBefore(bucket);
+
+	/* if the bucket is occupied, then it is returned immediately */
+	if(getBit(bucket)==1){
+		VALUE*vectorPointer=(VALUE*)allocator->getPointer(m_vector);
+		#ifdef ASSERT
+		VALUE*value=vectorPointer+bucketsBefore;
+		assert(value->getKey()==*key);
+		#endif
+		return vectorPointer+bucketsBefore;
+	}
+
+	/* make sure that it is not occupied by some troll already */
+	#ifdef ASSERT
+	assert(getBit(bucket)==0);
+	#endif
+
+	#ifdef ASSERT
+	int usedBucketsBefore=getUsedBuckets();
+	#endif
+
+	/* the bucket is not occupied */
+	setBit(bucket,1);
+
+	#ifdef ASSERT
+	assert(getUsedBuckets()==usedBucketsBefore+1);
+	#endif
+
+	/* compute the number of buckets to actually move. */
+	int bucketsAfter=0;
+	for(int i=bucket+1;i<numberOfBucketsInGroup;i++)
+		bucketsAfter+=getBit(i);
+
+	/* will allocate a new vector with one more element */
+	int requiredElements=(bucketsBefore+1+bucketsAfter);
+	SmartPointer newVector=allocator->allocate(requiredElements);
+
+	VALUE*newVectorPointer=(VALUE*)allocator->getPointer(newVector);
+	VALUE*vectorPointer=(VALUE*)allocator->getPointer(m_vector);
+
+	/* copy the buckets before */
+	for(int i=0;i<bucketsBefore;i++)
+		newVectorPointer[i]=vectorPointer[i];
+
+	/* copy the buckets after */
+	for(int i=0;i<bucketsAfter;i++)
+		newVectorPointer[bucketsBefore+1+i]=vectorPointer[bucketsBefore+i];
+
+	/* assign the new bucket */
+	newVectorPointer[bucketsBefore].setKey(*key);
+	
+	/* garbage the old vector, ChunkAllocatorWithDefragmentation will reuse it */
+	if(m_vector!=SmartPointer_NULL)
+		allocator->deallocate(m_vector);
+
+	/* assign the vector */
+	m_vector=newVector;
+
+	/* check that everything is OK now ! */
+	#ifdef ASSERT
+	assert(getBit(bucket)==1);
+	if(getBucket(bucket,allocator)->getKey()!=*key){
+		cout<<"Expected"<<endl;
+		key->print();
+		cout<<"Actual"<<endl;
+		getBucket(bucket,allocator)->getKey().print();
+		
+		cout<<"Bucket= "<<bucket<<" BucketsBefore= "<<bucketsBefore<<" BucketsAfter= "<<bucketsAfter<<endl;
+	}
+	assert(getBucket(bucket,allocator)->getKey()==*key);
+	assert(!bucketIsUtilisedBySomeoneElse(bucket,key,allocator));
+	#endif
+
+	/** check that we inserted something somewhere actually */
+	#ifdef ASSERT
+	assert(find(bucket,key,allocator)!=NULL);
+	assert(find(bucket,key,allocator)->getKey()==*key);
+	#endif
+
+	/** tell the caller that we inserted something  somewhere */
+	*inserted=true;
+
+	newVectorPointer=(VALUE*)allocator->getPointer(m_vector);
+	return newVectorPointer+bucketsBefore;
+}
+
+/** checks that the bucket is not utilised by someone else than key */
+template<class KEY,class VALUE>
+bool MyHashTableGroup<KEY,VALUE>::bucketIsUtilisedBySomeoneElse(int bucket,KEY*key,
+	ChunkAllocatorWithDefragmentation*allocator){
+	/** bucket is not used and therefore nobody uses it yet */
+	if(getBit(bucket)==0)
+		return false;
+
+	/** get the number of buckets before */
+	int bucketsBefore=getBucketsBefore(bucket);
+
+	/** check if the key is the same */
+	VALUE*vectorPointer=(VALUE*)allocator->getPointer(m_vector);
+	return vectorPointer[bucketsBefore].getKey()!=*key;
+}
+
+/** get direct access to the bucket 
+ * \pre the bucket must be used or the code fails
+ * */
+template<class KEY,class VALUE>
+VALUE*MyHashTableGroup<KEY,VALUE>::getBucket(int bucket,ChunkAllocatorWithDefragmentation*allocator){
+	/*  the bucket is not occupied therefore the key does not exist */
+	#ifdef ASSERT
+	assert(getBit(bucket)!=0);
+	if(m_vector==SmartPointer_NULL)
+		cout<<"bucket: "<<bucket<<endl;
+	assert(m_vector!=SmartPointer_NULL);
+	#endif
+
+	/* compute the number of elements before bucket */
+	int bucketsBefore=getBucketsBefore(bucket);
+
+	/* return the bucket */
+	VALUE*vectorPointer=(VALUE*)allocator->getPointer(m_vector);
+
+	#ifdef ASSERT
+	assert(vectorPointer!=NULL);
+	#endif
+
+	return vectorPointer+bucketsBefore;
+}
+
+/** get the number of occupied buckets before bucket 
+ * this is done by summing the bits of all buckets before bucket
+ */
+template<class KEY,class VALUE>
+int MyHashTableGroup<KEY,VALUE>::getBucketsBefore(int bucket){
+	
+	uint64_t mask=1;
+	mask<<=bucket;
+	mask-=1;
+
+	return __countBits( m_bitmap & mask );
+}
+
+/** finds a key in a bucket  
+ * this will *fail* if another key is found.
+ * */
+template<class KEY,class VALUE>
+VALUE*MyHashTableGroup<KEY,VALUE>::find(int bucket,KEY*key,ChunkAllocatorWithDefragmentation*allocator){
+
+	/*  the bucket is not occupied therefore the key does not exist */
+	if(getBit(bucket)==0){
+		return NULL;
+	}
+
+	/** the bucket should contains key at this point */
+	#ifdef ASSERT
+	assert(!bucketIsUtilisedBySomeoneElse(bucket,key,allocator));
+	#endif
+
+	/* compute the number of elements before bucket */
+	int bucketsBefore=getBucketsBefore(bucket);
+
+	/** return the pointer m_vector with the offset valued by bucketsBefore */
+	VALUE*vectorPointer=(VALUE*)allocator->getPointer(m_vector);
+	return vectorPointer+bucketsBefore;
+}
+
+#ifdef __hardware_debugging_gnuc
+template<class KEY,class VALUE>
+void MyHashTableGroup<KEY,VALUE>::__hash_print64(uint64_t a){
+	for(int k=63;k>=0;k-=2){
+		int bit=a<<(k-1)>>63;
+		printf("%i",bit);
+		bit=a<<(k)>>63;
+		printf("%i ",bit);
+	}
+	printf("\n");
+}
+#endif /* __hardware_debugging_gnuc */
+
+
+/* 
+ * get the number of used buckets */
+template<class KEY,class VALUE>
+int MyHashTableGroup<KEY,VALUE>::getUsedBuckets(){
+
+	return __countBits(m_bitmap);
+}
+
+/**
+ * could also use _mm_popcnt_u64
+ *
+ * \see http://www.dalkescientific.com/writings/diary/archive/2011/11/02/faster_popcount_update.html
+ */
+template<class KEY,class VALUE>
+int MyHashTableGroup<KEY,VALUE>::__countBits(uint64_t map){
+
+	#define KNUTH
+	//#define CONFIG_SSE_4_2
+	//#define CONFIG_HAS_POPCNT
+
+	/** Support is indicated via the CPUID.01H:ECX.POPCNT[Bit 23] flag. (Wikipedia **/
+	/* \see http://stackoverflow.com/questions/6427473/how-to-generate-a-sse4-2-popcnt-machine-instruction */
+	#if defined (CONFIG_HAS_POPCNT)
+
+	return _mm_popcnt_u64 (map);
+
+
+	/* this is the default on 64-bit gnu systems */
+	/* \see http://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Other-Builtins.html  */
+	#elif  defined (__GNUC__) && defined (__WORDSIZE) && __WORDSIZE == 64
+
+	return  __builtin_popcountll( map );
+
+	/* for Microsoft */
+	/* \see http://msdn.microsoft.com/en-us/library/bb385231.aspx  */
+	#elif defined (_MSC_VER) // should work on _WIN64 or _WIN32
+
+	
+	return __popcnt64 ( map ) ;
+
+	
+	#elif defined(KNUTH)
+
+	// from http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36041
+	
+	map = (map & 0x5555555555555555ULL) + ((map >> 1) & 0x5555555555555555ULL);
+	map = (map & 0x3333333333333333ULL) + ((map >> 2) & 0x3333333333333333ULL);
+	map = (map & 0x0F0F0F0F0F0F0F0FULL) + ((map >> 4) & 0x0F0F0F0F0F0F0F0FULL);
+	return (map * 0x0101010101010101ULL) >> 56;
+
+
+	#else
+
+	// silly implementation, slow.
+
+	int bits=0;
+	int i=0;
+	while(i<64){
+		bits+=((<map<(63-i))>>63);
+		i++;
+	}
+
+	return bits;
+
+	#endif
+
+	#undef KNUTH
+}
+
+#endif /* _MyHashTableGroup_hh */
+
+
diff --git a/RayPlatform/structures/MyHashTableIterator.h b/RayPlatform/structures/MyHashTableIterator.h
new file mode 100644
index 0000000..087c826
--- /dev/null
+++ b/RayPlatform/structures/MyHashTableIterator.h
@@ -0,0 +1,79 @@
+/*
+ 	Ray
+    Copyright (C) 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _MyHashTableIterator_H
+#define _MyHashTableIterator_H
+
+#include <structures/MyHashTable.h>
+#include <assert.h>
+
+/**
+ * \author Sébastien Boisvert
+ */
+template<class KEY,class VALUE>
+class MyHashTableIterator{
+	MyHashTable<KEY,VALUE>*m_table;
+	uint64_t m_i;
+	bool m_hasNext;
+	
+	void getNext();
+
+public: 
+	void constructor(MyHashTable<KEY,VALUE>*a);
+	bool hasNext();
+	VALUE*next();
+};
+
+template<class KEY,class VALUE>
+void MyHashTableIterator<KEY,VALUE>::constructor(MyHashTable<KEY,VALUE>*a){
+	m_i=0;
+	m_table=a;
+	getNext();
+
+	#ifdef ASSERT
+	assert(!a->needsToCompleteResizing());
+	#endif
+}
+
+template<class KEY,class VALUE>
+void MyHashTableIterator<KEY,VALUE>::getNext(){
+	while(m_i<m_table->capacity()&&m_table->isAvailable(m_i))
+		m_i++;
+	m_hasNext=m_i<m_table->capacity()&&!m_table->isAvailable(m_i);
+}
+
+template<class KEY,class VALUE>
+bool MyHashTableIterator<KEY,VALUE>::hasNext(){
+	return m_hasNext;
+}
+
+template<class KEY,class VALUE>
+VALUE*MyHashTableIterator<KEY,VALUE>::next(){
+	#ifdef ASSERT
+	assert(m_i<m_table->capacity());
+	#endif
+	VALUE*a=m_table->at(m_i);
+	m_i++;
+	getNext();
+	return a;
+}
+
+#endif
diff --git a/RayPlatform/structures/MyStack.h b/RayPlatform/structures/MyStack.h
new file mode 100644
index 0000000..b88290d
--- /dev/null
+++ b/RayPlatform/structures/MyStack.h
@@ -0,0 +1,78 @@
+/*
+ 	Ray
+    Copyright (C)  2010  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _MyStack
+#define _MyStack
+
+#include<assert.h>
+#define _MAX_STACK_SIZE 1024
+
+/**
+ * \author Sébastien Boisvert
+ */
+template<class TYPE>
+class MyStack{
+	TYPE m_array[_MAX_STACK_SIZE]; // maximum size 
+	int m_size;
+public:
+	TYPE top()const;
+	void pop();
+	int size()const;
+	void push(TYPE a);
+	MyStack();
+	bool empty()const;
+};
+
+
+template<class TYPE>
+bool MyStack<TYPE>::empty()const{
+	return m_size==0;
+}
+
+template<class TYPE>
+MyStack<TYPE>::MyStack(){
+	m_size=0;
+}
+
+template<class TYPE>
+TYPE MyStack<TYPE>::top()const{
+	return m_array[m_size-1];
+}
+
+template<class TYPE>
+void MyStack<TYPE>::pop(){
+	m_size--;
+}
+
+template<class TYPE>
+int MyStack<TYPE>::size() const{
+	return m_size;
+}
+
+template<class TYPE>
+void MyStack<TYPE>::push(TYPE a){
+	#ifdef ASSERT
+	assert(m_size!=_MAX_STACK_SIZE);
+	#endif
+	m_array[m_size++]=a;
+}
+
+#endif
+
diff --git a/RayPlatform/structures/SplayNode.h b/RayPlatform/structures/SplayNode.h
new file mode 100644
index 0000000..2a05d75
--- /dev/null
+++ b/RayPlatform/structures/SplayNode.h
@@ -0,0 +1,105 @@
+/*
+ 	Ray
+    Copyright (C)  2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _SplayNode
+#define _SplayNode
+
+#include<iostream>
+using namespace std;
+
+/**
+ * a splay node.
+ * \author Sébastien Boisvert
+ */
+template<class KEY,class VALUE>
+class SplayNode{
+public:
+	KEY m_key;
+	VALUE m_value;
+	SplayNode<KEY,VALUE>*m_left;
+	SplayNode<KEY,VALUE>*m_right;
+
+	SplayNode(KEY key);
+	SplayNode();
+	void setLeft(SplayNode<KEY,VALUE>*vertex);
+	void setRight(SplayNode<KEY,VALUE>*vertex);
+	KEY getKey()const;
+	void init(KEY key);
+	SplayNode<KEY,VALUE>*getLeft()const;
+	SplayNode<KEY,VALUE>*getRight()const;
+	VALUE*getValue();
+	void setValue(VALUE v);
+};
+
+template<class KEY,class VALUE>
+VALUE*SplayNode<KEY,VALUE>::getValue(){
+	return &m_value;
+}
+
+template<class KEY,class VALUE>
+void SplayNode<KEY,VALUE>::setValue(VALUE v){
+	m_value=v;
+}
+
+template<class KEY,class VALUE>
+SplayNode<KEY,VALUE>*SplayNode<KEY,VALUE>::getRight()const{
+	return m_right;
+}
+
+template<class KEY,class VALUE>
+SplayNode<KEY,VALUE>*SplayNode<KEY,VALUE>::getLeft()const{
+	return m_left;
+}
+
+template<class KEY,class VALUE>
+void SplayNode<KEY,VALUE>::init(KEY key){
+	m_key=key;
+	m_left=NULL;
+	m_right=NULL;
+}
+
+template<class KEY,class VALUE>
+KEY SplayNode<KEY,VALUE>::getKey()const{
+	return m_key;
+}
+
+template<class KEY,class VALUE>
+void SplayNode<KEY,VALUE>::setLeft(SplayNode<KEY,VALUE>*vertex){
+	m_left=vertex;
+}
+
+template<class KEY,class VALUE>
+void SplayNode<KEY,VALUE>::setRight(SplayNode<KEY,VALUE>*vertex){
+	m_right=vertex;
+}
+
+template<class KEY,class VALUE>
+SplayNode<KEY,VALUE>::SplayNode(KEY key){
+	init(key);
+}
+
+template<class KEY,class VALUE>
+SplayNode<KEY,VALUE>::SplayNode(){
+	m_left=NULL;
+	m_right=NULL;
+}
+
+#endif
+
diff --git a/RayPlatform/structures/SplayTree.h b/RayPlatform/structures/SplayTree.h
new file mode 100644
index 0000000..e64d1c1
--- /dev/null
+++ b/RayPlatform/structures/SplayTree.h
@@ -0,0 +1,281 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+*/
+
+#ifndef _SplayTree
+#define _SplayTree
+
+#include<structures/MyStack.h>
+#include<vector>
+#include<stdlib.h>
+#include<structures/SplayNode.h>
+#include<iostream>
+#include<memory/MyAllocator.h>
+using namespace std;
+
+/**
+ * the splay tree is a binary tree. If a key is asked often, the key will be near the root, otherwise, it will be deeper.
+ * this eases the processing because sequencing errors are kept far away from the root.
+ *
+ * \see http://www.eli.sdsu.edu/courses/fall95/cs660/notes/splay/Splay.html
+ * \see http://www.cs.nyu.edu/algvis/java/SplayTree.html
+ * \see ftp://ftp.cs.cmu.edu/user/sleator/splaying/SplayTree.java
+ * \author Sébastien Boisvert
+*/
+template<class KEY,class VALUE>
+class SplayTree{
+	SplayNode<KEY,VALUE>*m_root;
+	uint64_t m_size;
+	void splay(KEY key);
+public:
+	void constructor();
+	// freeze the splay tree.
+	bool remove(KEY key,bool reuse,MyAllocator*allocator);
+	SplayNode<KEY,VALUE>*insert(KEY key,MyAllocator*allocator,bool*inserted);
+	SplayNode<KEY,VALUE>*find(KEY key,bool frozen);
+	SplayNode<KEY,VALUE>*findBinary(KEY key);
+	void print();
+	SplayNode<KEY,VALUE>*getRoot();
+	uint64_t size();
+	void clear();
+};
+
+template<class KEY,class VALUE>
+void SplayTree<KEY,VALUE>::clear(){
+	// the allocator will be released elsewhere
+	m_root=NULL;
+	m_size=0;
+}
+
+template<class KEY,class VALUE>
+uint64_t SplayTree<KEY,VALUE>::size(){
+	return m_size;
+}
+
+template<class KEY,class VALUE>
+void SplayTree<KEY,VALUE>::constructor(){
+	m_root=NULL;
+	m_size=0;
+}
+
+/*
+ *
+ * based on http://www.cs.umbc.edu/courses/undergraduate/341/fall98/frey/ClassNotes/Class17/splay.html
+ */
+template<class KEY,class VALUE>
+bool SplayTree<KEY,VALUE>::remove(KEY key,bool reuse,MyAllocator*allocator){
+	// can't remove from an empty tree
+	if(m_root==NULL){
+		return false;
+	}
+	// make the node with key at root
+	splay(key);
+
+	// the key is not in the tree
+	if(m_root->getKey()!=key){
+		return false;
+	}
+	SplayNode<KEY,VALUE>*leftSubTree=m_root->getLeft();
+	SplayNode<KEY,VALUE>*rightSubTree=m_root->getRight();
+	SplayNode<KEY,VALUE>*toRemove=m_root;
+
+	if(leftSubTree!=NULL){
+		// we only work on the left subtree
+		m_root=leftSubTree;
+
+		// find the max node in left tree
+		SplayNode<KEY,VALUE>*maxNodeInLeftTree=leftSubTree;
+		while(maxNodeInLeftTree->getRight()!=NULL){
+			maxNodeInLeftTree=maxNodeInLeftTree->getRight();
+		}
+
+		// make it the root of the subtree
+		splay(maxNodeInLeftTree->getKey());
+
+		// set the right subtree to the right tree of the root
+		m_root->setRight(rightSubTree);
+	}else{
+		m_root=rightSubTree;
+	}
+
+	m_size--;
+
+	// reuse the pointer 
+	if(reuse){
+		allocator->free(toRemove,sizeof(SplayNode<KEY,VALUE>));
+	}
+	return true;
+}
+
+template<class KEY,class VALUE>
+SplayNode<KEY,VALUE>*SplayTree<KEY,VALUE>::getRoot(){
+	return m_root;
+}
+
+/*
+ * find x, if it is not there, call the last vertex visited during the search y, and splay y
+ * then, add x as root, and put y as child of x (left or right)
+ */
+template<class KEY,class VALUE>
+SplayNode<KEY,VALUE>*SplayTree<KEY,VALUE>::insert(KEY key,MyAllocator*allocator,bool*inserted){
+	(*inserted)=false;
+	if(m_root==NULL){
+		m_root=(SplayNode<KEY,VALUE>*)allocator->allocate(sizeof(SplayNode<KEY,VALUE>));
+		m_root->init(key);
+		(*inserted)=true;
+		m_size++;
+		return m_root;
+	}
+	splay(key);
+	if(m_root->getKey()==key)
+		return m_root;
+	SplayNode<KEY,VALUE>*n=(SplayNode<KEY,VALUE>*)allocator->allocate(sizeof(SplayNode<KEY,VALUE>));
+	n->init(key);
+	
+	if(key<m_root->getKey()){
+		n->m_left=m_root->m_left;
+		n->m_right=m_root;
+		m_root->m_left=NULL;
+	}else{
+		n->m_right=m_root->m_right;
+		n->m_left=m_root;
+		m_root->m_right=NULL;
+	}
+	m_root=n;
+	m_size++;
+	(*inserted)=true;
+	return m_root;
+}
+
+template<class KEY,class VALUE>
+SplayNode<KEY,VALUE>*SplayTree<KEY,VALUE>::findBinary(KEY key){
+	SplayNode<KEY,VALUE>*t=m_root;
+	while(t!=NULL){
+		if(t->m_key==key){
+			return t;
+		}else if(key<t->m_key){
+			t=t->m_left;
+		}else{
+			t=t->m_right;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * binarySearch(x), if it is not there, return NULL
+ * splay(x)
+ * return the root
+ */
+template<class KEY,class VALUE>
+SplayNode<KEY,VALUE>*SplayTree<KEY,VALUE>::find(KEY key,bool frozen){
+	if(frozen){
+		return findBinary(key);
+	}
+
+	if(m_root==NULL)
+		return NULL;
+	splay(key);
+	if(m_root->getKey()!=key)
+		return NULL;
+	return m_root;
+}
+
+template<class KEY,class VALUE>
+void SplayTree<KEY,VALUE>::print(){
+	cout<<"digraph{"<<endl;
+	MyStack<SplayNode<KEY,VALUE>*> vertices;
+	MyStack<int> depths;
+	if(m_root!=NULL){
+		vertices.push(m_root);
+		depths.push(0);
+	}
+	while(vertices.size()>0){
+		SplayNode<KEY,VALUE>*u=vertices.top();
+		vertices.pop();
+		int d=depths.top();
+		depths.pop();
+		cout<<"\""<<u->getKey()<<"\""<<endl;
+
+		if(u->getLeft()!=NULL){
+			vertices.push(u->getLeft());
+			cout<<"\""<<u->getKey()<<"\""<<" -> "<<"\""<<u->getLeft()->getKey()<<"\""<<endl;
+			depths.push(d+1);
+		}
+
+		if(u->getRight()!=NULL){
+			vertices.push(u->getRight());
+			cout<<"\""<<u->getKey()<<"\""<<" -> "<<"\""<<u->getRight()->getKey()<<"\""<<endl;
+			depths.push(d+1);
+		}
+	}
+	cout<<"}"<<endl;
+}
+
+template<class KEY,class VALUE>
+void SplayTree<KEY,VALUE>::splay(KEY key){
+	SplayNode<KEY,VALUE> header;
+	SplayNode<KEY,VALUE>*l;
+	SplayNode<KEY,VALUE>*r;
+	SplayNode<KEY,VALUE>*t;
+	SplayNode<KEY,VALUE>*y;
+	l=r=&header;
+	t=m_root;
+	header.m_left=header.m_right=NULL;
+	while(1){
+		if(key<t->m_key){
+			if(t->m_left==NULL)
+				break;
+			if(key<t->m_left->m_key){
+				y=t->m_left;
+				t->m_left=y->m_right;
+				y->m_right=t;
+				t=y;
+				if(t->m_left==NULL)
+					break;
+			}
+			r->m_left=t;
+			r=t;
+			t=t->m_left;
+		}else if(t->m_key<key){
+			if(t->m_right==NULL)
+				break;
+			if(t->m_right->m_key<key){
+				y=t->m_right;
+				t->m_right=y->m_left;
+				y->m_left=t;
+				t=y;
+				if(t->m_right==NULL)
+					break;
+			}
+			l->m_right=t;
+			l=t;
+			t=t->m_right;
+		}else{
+			break;
+		}
+	}
+	l->m_right=t->m_left;
+	r->m_left=t->m_right;
+	t->m_left=header.m_right;
+	t->m_right=header.m_left;
+	m_root=t;
+}
+
+#endif
diff --git a/RayPlatform/structures/SplayTreeIterator.h b/RayPlatform/structures/SplayTreeIterator.h
new file mode 100644
index 0000000..456eb71
--- /dev/null
+++ b/RayPlatform/structures/SplayTreeIterator.h
@@ -0,0 +1,121 @@
+/*
+ 	Ray
+    Copyright (C)  2010  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _SplayTreeIterator
+#define _SplayTreeIterator
+
+#include<structures/MyStack.h>
+#include<structures/SplayNode.h>
+#include<structures/SplayTree.h>
+#include<assert.h>
+#include<stdlib.h>
+
+/**
+ * An iterator on SplayTree
+ * \author Sébastien Boisvert
+ */
+template<class TREE_KEY_TYPE,class TREE_VALUE_TYPE>
+class SplayTreeIterator{
+	MyStack<SplayNode<TREE_KEY_TYPE,TREE_VALUE_TYPE>*>m_stack;
+	SplayTree<TREE_KEY_TYPE,TREE_VALUE_TYPE>*m_tree;
+	int m_processed;
+	int m_id;
+	int m_rank;
+	int m_treeSize;
+public:
+	SplayTreeIterator(SplayTree<TREE_KEY_TYPE,TREE_VALUE_TYPE>*tree);
+	void constructor(SplayTree<TREE_KEY_TYPE,TREE_VALUE_TYPE>*tree);
+	SplayTreeIterator();
+	bool hasNext() const;
+	SplayNode<TREE_KEY_TYPE,TREE_VALUE_TYPE>*next();
+	void setId(int a);
+	void setRank(int i);
+};
+
+
+template<class TREE_KEY_TYPE,class TREE_VALUE_TYPE>
+SplayTreeIterator<TREE_KEY_TYPE,TREE_VALUE_TYPE>::SplayTreeIterator(){
+	m_tree=NULL;
+	m_processed=-1;
+	m_id=-1;
+	m_treeSize=-1;
+}
+
+template<class TREE_KEY_TYPE,class TREE_VALUE_TYPE>
+SplayTreeIterator<TREE_KEY_TYPE,TREE_VALUE_TYPE>::SplayTreeIterator(SplayTree<TREE_KEY_TYPE,TREE_VALUE_TYPE>*tree){
+	constructor(tree);
+}
+
+template<class TREE_KEY_TYPE,class TREE_VALUE_TYPE>
+void SplayTreeIterator<TREE_KEY_TYPE,TREE_VALUE_TYPE>::constructor(SplayTree<TREE_KEY_TYPE,TREE_VALUE_TYPE>*tree){
+	#ifdef ASSERT
+	assert(m_stack.size()==0);
+	#endif
+	m_tree=tree;
+	m_processed=0;
+	m_treeSize=m_tree->size();
+	if(m_tree!=NULL && m_tree->getRoot()!=NULL){
+		m_stack.push(tree->getRoot());
+	}
+}
+
+template<class TREE_KEY_TYPE,class TREE_VALUE_TYPE>
+bool SplayTreeIterator<TREE_KEY_TYPE,TREE_VALUE_TYPE>::hasNext()const{
+	#ifdef ASSERT
+	if(m_stack.size()==0 && m_tree!=NULL){
+		if(m_processed!=(int)m_tree->size()){
+			cout<<"Rank="<<m_rank<<" id="<<m_id<<" Processed="<<m_processed<<" Tree="<<m_tree->size()<<" onRecord="<<m_treeSize<<endl;
+		}
+		assert(m_processed==(int)m_tree->size());
+	}
+	#endif
+	return m_stack.size()>0;
+}
+
+template<class TREE_KEY_TYPE,class TREE_VALUE_TYPE>
+SplayNode<TREE_KEY_TYPE,TREE_VALUE_TYPE>*SplayTreeIterator<TREE_KEY_TYPE,TREE_VALUE_TYPE>::next(){
+	if(hasNext()){
+		SplayNode<TREE_KEY_TYPE,TREE_VALUE_TYPE>*c=m_stack.top();
+		m_stack.pop();
+		if(c->getLeft()!=NULL){
+			m_stack.push(c->getLeft());
+		}
+		if(c->getRight()!=NULL){
+			m_stack.push(c->getRight());
+		}
+		m_processed++;
+		return c;
+	}else{
+		return NULL;
+	}
+}
+
+template<class TREE_KEY_TYPE,class TREE_VALUE_TYPE>
+void SplayTreeIterator<TREE_KEY_TYPE,TREE_VALUE_TYPE>::setId(int a){
+	m_id=a;
+}
+
+template<class TREE_KEY_TYPE,class TREE_VALUE_TYPE>
+void SplayTreeIterator<TREE_KEY_TYPE,TREE_VALUE_TYPE>::setRank(int rank){
+	m_rank=rank;
+}
+
+#endif
diff --git a/RayPlatform/structures/StaticVector.cpp b/RayPlatform/structures/StaticVector.cpp
new file mode 100644
index 0000000..57068e8
--- /dev/null
+++ b/RayPlatform/structures/StaticVector.cpp
@@ -0,0 +1,71 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#include <structures/StaticVector.h>
+#include <memory/allocator.h>
+
+#include <assert.h>
+#include <string.h>
+
+void StaticVector::constructor(int size,const char* type,bool show){
+	strcpy(m_type,type);
+
+	#ifdef ASSERT
+	assert(size!=0);
+	#endif
+
+	m_maxSize=size;
+	m_messages=(Message*)__Malloc(sizeof(Message)*m_maxSize,m_type,show);
+	m_size=0;
+}
+
+Message*StaticVector::operator[](int i){
+	return at(i);
+}
+
+Message*StaticVector::at(int i){
+	#ifdef ASSERT
+	assert(i<m_size);
+	#endif
+	return m_messages+i;
+}
+
+// TODO: the message a should be passed as a pointer
+void StaticVector::push_back(Message a){
+	m_messages[m_size++]=a;
+}
+
+int StaticVector::size(){
+	return m_size;
+}
+
+void StaticVector::clear(){
+	m_size=0;
+}
+
+bool StaticVector::hasMessage(MessageTag tag){
+	for(int i=0;i<m_size;i++){
+		if(at(i)->getTag()==tag)
+			return true;
+	}
+
+	return false;
+}
diff --git a/RayPlatform/structures/StaticVector.h b/RayPlatform/structures/StaticVector.h
new file mode 100644
index 0000000..563e637
--- /dev/null
+++ b/RayPlatform/structures/StaticVector.h
@@ -0,0 +1,53 @@
+/*
+ 	Ray
+    Copyright (C) 2010, 2011  Sébastien Boisvert
+
+	http://DeNovoAssembler.SourceForge.Net/
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation, version 3 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You have received a copy of the GNU Lesser General Public License
+    along with this program (lgpl-3.0.txt).  
+	see <http://www.gnu.org/licenses/>
+
+*/
+
+#ifndef _StaticVector
+#define _StaticVector
+
+#include <communication/Message.h>
+#include <communication/mpi_tags.h>
+
+/**
+ * A static vector of Message.
+ * This is used for the inbox and the outbox in Ray
+ *
+ * clear is basically O(1), it just sets m_size=0
+ * \author Sébastien Boisvert
+ */
+class StaticVector{
+	Message*m_messages;
+	int m_size;
+	int m_maxSize;
+	char m_type[100];
+public:
+	Message*operator[](int i);
+	Message*at(int i);
+
+	// TODO: messages should be passed by reference or pointer
+	void push_back(Message a);
+	int size();
+	void clear();
+	void constructor(int size,const char*type,bool show);
+
+	bool hasMessage(MessageTag tag);
+};
+
+#endif
diff --git a/RayPlatform/tag.txt b/RayPlatform/tag.txt
new file mode 100644
index 0000000..b74810d
--- /dev/null
+++ b/RayPlatform/tag.txt
@@ -0,0 +1 @@
+7ceb2d018d4f549ddce375d1ef0f28ae2112c87b
diff --git a/git.txt b/git.txt
new file mode 100644
index 0000000..edf226f
--- /dev/null
+++ b/git.txt
@@ -0,0 +1 @@
+git://github.com/sebhtml/ray.git
diff --git a/github.txt b/github.txt
new file mode 100644
index 0000000..843b1d3
--- /dev/null
+++ b/github.txt
@@ -0,0 +1 @@
+https://github.com/sebhtml/ray
diff --git a/tag.txt b/tag.txt
new file mode 100644
index 0000000..bd3efae
--- /dev/null
+++ b/tag.txt
@@ -0,0 +1 @@
+c8953003b7b3bdfda399fc49c11c0e15889332cd

-- 
Packaging of Ray in Debian



More information about the debian-med-commit mailing list