From ef2396bb5e5e10c076f946a106ef19171140beec Mon Sep 17 00:00:00 2001
From: Alexander Peyser <a.peyser@fz-juelich.de>
Date: Wed, 3 Jun 2015 13:29:29 +0200
Subject: [PATCH] Initial commit from svn multiconn branch

not released version
SVN: multiconn@1048
---
 .gitignore                             |    19 +
 AUTHORS                                |    11 +
 BUGS                                   |     3 +
 COPYING                                |   674 +
 ChangeLog                              |   205 +
 INSTALL                                |   234 +
 Makefile.am                            |    33 +
 NEWS                                   |    92 +
 PORTING                                |    78 +
 README                                 |   111 +
 RELEASE                                |    25 +
 TODO                                   |   105 +
 acinclude.m4                           |    70 +
 aclocal.sh                             |    21 +
 autogen.sh                             |    24 +
 configure.ac                           |   406 +
 debian/changelog                       |    33 +
 debian/compat                          |     1 +
 debian/control                         |    60 +
 debian/copyright                       |    37 +
 debian/docs                            |     4 +
 debian/libmusic-dev.dirs               |     3 +
 debian/libmusic-dev.docs               |     4 +
 debian/libmusic-dev.install            |     4 +
 debian/libmusic1.dirs                  |     1 +
 debian/libmusic1.docs                  |     4 +
 debian/libmusic1.install               |     1 +
 debian/music-bin.dirs                  |     1 +
 debian/music-bin.docs                  |     3 +
 debian/music-bin.install               |     2 +
 debian/music-doc.dirs                  |     1 +
 debian/music-doc.doc-base              |    16 +
 debian/music-doc.docs                  |     4 +
 debian/rules                           |   116 +
 doc/.gitignore                         |    21 +
 doc/ChangeLog                          |    38 +
 doc/Makefile.am                        |    62 +
 doc/eventcounter.1                     |   134 +
 doc/figures/.gitignore                 |     7 +
 doc/figures/dataconvergence.asy        |    21 +
 doc/figures/datamapping.asy            |    56 +
 doc/figures/messysim.asy               |   103 +
 doc/figures/multisim.asy               |    30 +
 doc/figures/receiverport.asy           |    22 +
 doc/figures/remapping.asy              |    46 +
 doc/figures/remapping2.asy             |    46 +
 doc/figures/senderport.asy             |    23 +
 doc/figures/ticklogic.asy              |    39 +
 doc/figures/ticklogic2.asy             |    38 +
 doc/figures/timeline.asy               |    41 +
 doc/music-c-int.h                      |   132 +
 doc/music-manual.tex                   |  1748 +++
 doc/music-rfc.bib                      |    15 +
 doc/music-rfc.tex                      |  1708 +++
 doc/music.1                            |    70 +
 doc/scheduling-algorithm.py            |   164 +
 doc/scheduling.text                    |    20 +
 examples/.gitignore                    |     2 +
 examples/Makefile.am                   |    24 +
 examples/README                        |    95 +
 examples/demo.music                    |    10 +
 examples/demolarge.music               |    10 +
 examples/makeNeuronGrid.m              |    30 +
 examples/makeTestSpikes.m              |    16 +
 examples/messages.music                |     9 +
 examples/messages0.dat                 |     2 +
 examples/messages1.dat                 |     3 +
 examples/neuronGrid.data               |    32 +
 examples/neuronGridLARGE.data          |  1003 ++
 examples/neuronGridPlane.data          |   532 +
 examples/spikes0.dat                   |    11 +
 examples/spikes1.dat                   |    11 +
 examples/viewevents.music              |     9 +
 examples/vieweventsLARGE.music         |     9 +
 examples/vieweventsPlane.music         |     9 +
 examples/waveconsumer.cc               |    59 +
 examples/waveproducer.cc               |    64 +
 examples/wavetest.music                |    10 +
 extras/Makefile.am                     |     7 +
 extras/music_mpirun                    |    20 +
 mpidep/.gitignore                      |     5 +
 mpidep/ChangeLog                       |    62 +
 mpidep/Makefile.am                     |    11 +
 mpidep/mpidep.cc                       |   201 +
 mpidep/mpidep.hh                       |    27 +
 music/.gitignore                       |     1 +
 music/ChangeLog                        |     8 +
 music/Makefile.am                      |    10 +
 music/__init__.py                      |    21 +
 music/config.py                        |   250 +
 music/get_rank.py                      |    29 +
 music/predict_rank.py.in               |    23 +
 pymusic-old/Makefile                   |     8 +
 pymusic-old/README                     |     6 +
 pymusic-old/helloworld                 |     2 +
 pymusic-old/helloworld.music           |     7 +
 pymusic-old/helloworld.py              |    20 +
 pymusic-old/late.h                     |     8 +
 pymusic-old/late.pxd                   |    11 +
 pymusic-old/late.pyx                   |    12 +
 pymusic-old/late_impl.h                |    10 +
 pymusic-old/music.pyx                  |     3 +
 pymusic-old/port.pxd                   |    11 +
 pymusic-old/port.pxi                   |    27 +
 pymusic-old/python_main.c              |    12 +
 pymusic-old/runtime.pxd                |    20 +
 pymusic-old/runtime.pxi                |    28 +
 pymusic-old/setup.pxd                  |    71 +
 pymusic-old/setup.pxi                  |    39 +
 pymusic-old/setup.py                   |    34 +
 pymusic-old/test.py                    |     8 +
 pymusic/.gitignore                     |     3 +
 pymusic/Makefile.am                    |    53 +
 pymusic/examples/event.music           |    14 +
 pymusic/examples/eventlogger.py        |    49 +
 pymusic/examples/eventsource.py        |    49 +
 pymusic/examples/helloworld.music      |     8 +
 pymusic/examples/message.music         |    15 +
 pymusic/examples/message.py            |    17 +
 pymusic/examples/messagelogger.py      |    37 +
 pymusic/examples/messagesource.py      |    38 +
 pymusic/examples/receivers.py          |    29 +
 pymusic/examples/senders.py            |    24 +
 pymusic/examples/test.music            |    13 +
 pymusic/examples/testsink.py           |    46 +
 pymusic/examples/testsource.py         |    56 +
 pymusic/music/__init__.py              |    29 +
 pymusic/music/music_c.h                |   178 +
 pymusic/music/pybuffer.pxd             |     1 +
 pymusic/music/pymusic.pxd              |     1 +
 pymusic/music/pymusic_c.h              |    12 +
 pymusic/pybuffer.cpp                   |  3564 ++++++
 pymusic/pybuffer.pxd                   |    43 +
 pymusic/pybuffer.pyx                   |    66 +
 pymusic/pymusic.cpp                    | 15159 +++++++++++++++++++++++
 pymusic/pymusic.pxd                    |   234 +
 pymusic/pymusic.pyx                    |   728 ++
 pymusic/setup.py.in                    |    13 +
 rudeconfig/.gitignore                  |     5 +
 rudeconfig/AUTHORS                     |    35 +
 rudeconfig/COPYING                     |   340 +
 rudeconfig/ChangeLog                   |   201 +
 rudeconfig/Makefile.am                 |    70 +
 rudeconfig/NEWS                        |   114 +
 rudeconfig/README                      |    66 +
 rudeconfig/THANKS                      |    10 +
 rudeconfig/man3/rudeconfig.3           |   276 +
 rudeconfig/src/AbstractData.cpp        |    43 +
 rudeconfig/src/AbstractData.h          |    49 +
 rudeconfig/src/AbstractOrganiser.cpp   |    42 +
 rudeconfig/src/AbstractOrganiser.h     |    57 +
 rudeconfig/src/AbstractParser.cpp      |    78 +
 rudeconfig/src/AbstractParser.h        |    73 +
 rudeconfig/src/AbstractWriter.cpp      |    83 +
 rudeconfig/src/AbstractWriter.h        |    79 +
 rudeconfig/src/Base64Encoder.cpp       |   331 +
 rudeconfig/src/Base64Encoder.h         |    64 +
 rudeconfig/src/Comment.cpp             |    58 +
 rudeconfig/src/Comment.h               |    57 +
 rudeconfig/src/ConfigImpl.cpp          |   616 +
 rudeconfig/src/ConfigImpl.h            |   199 +
 rudeconfig/src/DataLine.cpp            |    52 +
 rudeconfig/src/DataLine.h              |    63 +
 rudeconfig/src/File.cpp                |   341 +
 rudeconfig/src/File.h                  |    97 +
 rudeconfig/src/KeyValue.cpp            |    96 +
 rudeconfig/src/KeyValue.h              |   123 +
 rudeconfig/src/ParserJuly2004.cpp      |  1206 ++
 rudeconfig/src/ParserJuly2004.h        |    62 +
 rudeconfig/src/RealOrganiser.cpp       |    88 +
 rudeconfig/src/RealOrganiser.h         |    63 +
 rudeconfig/src/Section.cpp             |   415 +
 rudeconfig/src/Section.h               |   262 +
 rudeconfig/src/SourceDest.cpp          |   154 +
 rudeconfig/src/SourceDest.h            |   126 +
 rudeconfig/src/WhiteSpace.cpp          |    58 +
 rudeconfig/src/WhiteSpace.h            |    57 +
 rudeconfig/src/Writer.cpp              |   387 +
 rudeconfig/src/Writer.h                |   106 +
 rudeconfig/src/config.cpp              |   325 +
 rudeconfig/src/config.h                |   637 +
 src/.gitignore                         |     5 +
 src/BIFO.cc                            |   196 +
 src/ChangeLog                          |  1020 ++
 src/FIBO.cc                            |   108 +
 src/Makefile.am                        |    93 +
 src/application_map.cc                 |   160 +
 src/application_mapper.cc              |   409 +
 src/array_data.cc                      |    55 +
 src/clock.cc                           |    91 +
 src/collector.cc                       |   155 +
 src/configuration.cc                   |   314 +
 src/connection.cc                      |    47 +
 src/connectivity.cc                    |   243 +
 src/connector.cc                       |  1115 ++
 src/distributor.cc                     |   146 +
 src/error.cc                           |   127 +
 src/event_data.cc                      |    31 +
 src/event_router.cc                    |    75 +
 src/event_routing_map.cc               |   124 +
 src/index_map.cc                       |    67 +
 src/index_map_factory.cc               |    68 +
 src/interval.cc                        |    31 +
 src/ioutils.cc                         |    85 +
 src/linear_index.cc                    |    84 +
 src/memory.cc                          |    43 +
 src/multibuffer.cc                     |   963 ++
 src/music-c-c.c                        |    15 +
 src/music-c.cc                         |   519 +
 src/music-c.h                          |   209 +
 src/music.hh                           |    27 +
 src/music/.gitignore                   |     2 +
 src/music/BIFO.hh                      |    69 +
 src/music/FIBO.hh                      |    53 +
 src/music/application_graph.hh         |   393 +
 src/music/application_map.hh           |   103 +
 src/music/application_mapper.hh        |   155 +
 src/music/array_data.hh                |    46 +
 src/music/clock.hh                     |    84 +
 src/music/collector.hh                 |    82 +
 src/music/communication.hh             |    41 +
 src/music/configuration.hh             |   104 +
 src/music/connection.hh                |    72 +
 src/music/connectivity.hh              |   234 +
 src/music/connector.hh                 |   628 +
 src/music/cont_data.hh                 |    35 +
 src/music/data_map.hh                  |    53 +
 src/music/debug.hh                     |    76 +
 src/music/distributor.hh               |    76 +
 src/music/error.hh                     |    41 +
 src/music/event.hh                     |    97 +
 src/music/event_router.hh              |   253 +
 src/music/event_routing_map.hh         |   127 +
 src/music/index_map.hh                 |   113 +
 src/music/index_map_factory.hh         |    57 +
 src/music/interval.hh                  |    48 +
 src/music/interval_table.hh            |   383 +
 src/music/interval_tree.hh             |   190 +
 src/music/ioutils.hh                   |    34 +
 src/music/linear_index.hh              |    54 +
 src/music/memory.hh                    |    28 +
 src/music/message.hh                   |    75 +
 src/music/multibuffer.hh               |   374 +
 src/music/music-config.hh.in           |    32 +
 src/music/ordered_ilist.hh             |   259 +
 src/music/parse.hh                     |    41 +
 src/music/permutation_index.hh         |    59 +
 src/music/port.hh                      |   285 +
 src/music/predict_rank-c.h             |    24 +
 src/music/predict_rank.hh              |    28 +
 src/music/runtime.hh                   |    99 +
 src/music/sampler.hh                   |    67 +
 src/music/scheduler.hh                 |   234 +
 src/music/scheduler_agent.hh           |   294 +
 src/music/setup.hh                     |   171 +
 src/music/spatial.hh                   |   195 +
 src/music/spikes.hh                    |    37 +
 src/music/subconnector.hh              |   366 +
 src/music/temporal.hh                  |   168 +
 src/music/version.hh.in                |    34 +
 src/parse.cc                           |   129 +
 src/permutation_index.cc               |    59 +
 src/port.cc                            |   821 ++
 src/predict_rank-c.cc                  |    27 +
 src/predict_rank.cc                    |    29 +
 src/runtime.cc                         |   535 +
 src/sampler.cc                         |   239 +
 src/scheduler.cc                       |   644 +
 src/scheduler_agent.cc                 |   543 +
 src/setup.cc                           |   459 +
 src/spatial.cc                         |   604 +
 src/subconnector.cc                    |   888 ++
 src/temporal.cc                        |   502 +
 src/version.cc                         |    29 +
 testsuite/.gitignore                   |     1 +
 testsuite/Makefile.am                  |     9 +
 testsuite/music_tests.sh.in            |   353 +
 testsuite/sanitytests/.gitignore       |     6 +
 testsuite/sanitytests/Makefile.am      |    59 +
 testsuite/sanitytests/chain.test       |    94 +
 testsuite/sanitytests/clocksource.cc   |   153 +
 testsuite/sanitytests/cloop.test       |   163 +
 testsuite/sanitytests/const.test       |   253 +
 testsuite/sanitytests/constsource.cc   |   156 +
 testsuite/sanitytests/contclock.test   |    72 +
 testsuite/sanitytests/contdelay.cc     |   189 +
 testsuite/sanitytests/divergence.test  |    90 +
 testsuite/sanitytests/eventdelay.cc    |   243 +
 testsuite/sanitytests/events.test      |    82 +
 testsuite/sanitytests/fork.test        |    93 +
 testsuite/sanitytests/launchtest.cc    |    20 +
 testsuite/sanitytests/launchtest.test  |    56 +
 testsuite/sanitytests/loop.test        |   244 +
 testsuite/sanitytests/messages.test    |    74 +
 testsuite/sanitytests/multicomm.test   |    99 +
 testsuite/sanitytests/multiport.cc     |   441 +
 testsuite/sanitytests/multiport.test   |    54 +
 testsuite/sanitytests/run_test         |    43 +
 testsuite/test_old/ChangeLog           |   167 +
 testsuite/test_old/chain.music         |    15 +
 testsuite/test_old/cloop.music         |    19 +
 testsuite/test_old/coba.cc             |   350 +
 testsuite/test_old/const.music         |     8 +
 testsuite/test_old/contclock.music     |    10 +
 testsuite/test_old/divergence.music    |    10 +
 testsuite/test_old/events.music        |     9 +
 testsuite/test_old/events.py           |    12 +
 testsuite/test_old/fork.music          |    11 +
 testsuite/test_old/launcher.cc         |    27 +
 testsuite/test_old/launchtest.music    |    13 +
 testsuite/test_old/loop.music          |    20 +
 testsuite/test_old/multicomm.music     |    16 +
 testsuite/test_old/multipoisson.music  |    19 +
 testsuite/test_old/multipoisson2.music |    19 +
 testsuite/test_old/multiport.music     |    21 +
 testsuite/test_old/parsetest.cc        |    48 +
 testsuite/test_old/poisson.music       |    10 +
 testsuite/test_old/poisson2.music      |     9 +
 testsuite/unittests/catch/.gitignore   |     1 +
 testsuite/unittests/catch/Makefile.am  |    19 +
 testsuite/unittests/catch/catch.hpp    |  8891 +++++++++++++
 testsuite/unittests/catch/test_ag.cc   |   167 +
 utils/.gitignore                       |    15 +
 utils/ChangeLog                        |   187 +
 utils/Makefile.am                      |    54 +
 utils/VisualiseNeurons.cpp             |   631 +
 utils/VisualiseNeurons.h               |   177 +
 utils/contsink.cc                      |   135 +
 utils/datafile.cc                      |    99 +
 utils/datafile.h                       |    38 +
 utils/eventcounter.cc                  |   224 +
 utils/eventgenerator.cc                |   256 +
 utils/eventlogger.cc                   |   271 +
 utils/eventselect.cc                   |   246 +
 utils/eventsink.cc                     |   243 +
 utils/eventsource.cc                   |   243 +
 utils/messagesource.cc                 |   177 +
 utils/music.cc                         |   262 +
 utils/viewevents.cpp                   |    36 +
 339 files changed, 73033 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 AUTHORS
 create mode 100644 BUGS
 create mode 100644 COPYING
 create mode 100644 ChangeLog
 create mode 100644 INSTALL
 create mode 100644 Makefile.am
 create mode 100644 NEWS
 create mode 100644 PORTING
 create mode 100644 README
 create mode 100644 RELEASE
 create mode 100644 TODO
 create mode 100644 acinclude.m4
 create mode 100755 aclocal.sh
 create mode 100755 autogen.sh
 create mode 100644 configure.ac
 create mode 100644 debian/changelog
 create mode 100644 debian/compat
 create mode 100644 debian/control
 create mode 100644 debian/copyright
 create mode 100644 debian/docs
 create mode 100644 debian/libmusic-dev.dirs
 create mode 100644 debian/libmusic-dev.docs
 create mode 100644 debian/libmusic-dev.install
 create mode 100644 debian/libmusic1.dirs
 create mode 100644 debian/libmusic1.docs
 create mode 100644 debian/libmusic1.install
 create mode 100644 debian/music-bin.dirs
 create mode 100644 debian/music-bin.docs
 create mode 100644 debian/music-bin.install
 create mode 100644 debian/music-doc.dirs
 create mode 100644 debian/music-doc.doc-base
 create mode 100644 debian/music-doc.docs
 create mode 100755 debian/rules
 create mode 100644 doc/.gitignore
 create mode 100644 doc/ChangeLog
 create mode 100644 doc/Makefile.am
 create mode 100644 doc/eventcounter.1
 create mode 100644 doc/figures/.gitignore
 create mode 100644 doc/figures/dataconvergence.asy
 create mode 100644 doc/figures/datamapping.asy
 create mode 100644 doc/figures/messysim.asy
 create mode 100644 doc/figures/multisim.asy
 create mode 100644 doc/figures/receiverport.asy
 create mode 100644 doc/figures/remapping.asy
 create mode 100644 doc/figures/remapping2.asy
 create mode 100644 doc/figures/senderport.asy
 create mode 100644 doc/figures/ticklogic.asy
 create mode 100644 doc/figures/ticklogic2.asy
 create mode 100644 doc/figures/timeline.asy
 create mode 100644 doc/music-c-int.h
 create mode 100644 doc/music-manual.tex
 create mode 100644 doc/music-rfc.bib
 create mode 100644 doc/music-rfc.tex
 create mode 100644 doc/music.1
 create mode 100644 doc/scheduling-algorithm.py
 create mode 100644 doc/scheduling.text
 create mode 100644 examples/.gitignore
 create mode 100644 examples/Makefile.am
 create mode 100644 examples/README
 create mode 100644 examples/demo.music
 create mode 100644 examples/demolarge.music
 create mode 100644 examples/makeNeuronGrid.m
 create mode 100644 examples/makeTestSpikes.m
 create mode 100644 examples/messages.music
 create mode 100644 examples/messages0.dat
 create mode 100644 examples/messages1.dat
 create mode 100644 examples/neuronGrid.data
 create mode 100644 examples/neuronGridLARGE.data
 create mode 100644 examples/neuronGridPlane.data
 create mode 100644 examples/spikes0.dat
 create mode 100644 examples/spikes1.dat
 create mode 100644 examples/viewevents.music
 create mode 100644 examples/vieweventsLARGE.music
 create mode 100644 examples/vieweventsPlane.music
 create mode 100644 examples/waveconsumer.cc
 create mode 100644 examples/waveproducer.cc
 create mode 100644 examples/wavetest.music
 create mode 100644 extras/Makefile.am
 create mode 100755 extras/music_mpirun
 create mode 100644 mpidep/.gitignore
 create mode 100644 mpidep/ChangeLog
 create mode 100644 mpidep/Makefile.am
 create mode 100644 mpidep/mpidep.cc
 create mode 100644 mpidep/mpidep.hh
 create mode 100644 music/.gitignore
 create mode 100644 music/ChangeLog
 create mode 100644 music/Makefile.am
 create mode 100644 music/__init__.py
 create mode 100644 music/config.py
 create mode 100644 music/get_rank.py
 create mode 100644 music/predict_rank.py.in
 create mode 100644 pymusic-old/Makefile
 create mode 100644 pymusic-old/README
 create mode 100755 pymusic-old/helloworld
 create mode 100644 pymusic-old/helloworld.music
 create mode 100644 pymusic-old/helloworld.py
 create mode 100644 pymusic-old/late.h
 create mode 100644 pymusic-old/late.pxd
 create mode 100644 pymusic-old/late.pyx
 create mode 100644 pymusic-old/late_impl.h
 create mode 100644 pymusic-old/music.pyx
 create mode 100644 pymusic-old/port.pxd
 create mode 100644 pymusic-old/port.pxi
 create mode 100644 pymusic-old/python_main.c
 create mode 100644 pymusic-old/runtime.pxd
 create mode 100644 pymusic-old/runtime.pxi
 create mode 100644 pymusic-old/setup.pxd
 create mode 100644 pymusic-old/setup.pxi
 create mode 100644 pymusic-old/setup.py
 create mode 100644 pymusic-old/test.py
 create mode 100644 pymusic/.gitignore
 create mode 100644 pymusic/Makefile.am
 create mode 100644 pymusic/examples/event.music
 create mode 100755 pymusic/examples/eventlogger.py
 create mode 100755 pymusic/examples/eventsource.py
 create mode 100644 pymusic/examples/helloworld.music
 create mode 100644 pymusic/examples/message.music
 create mode 100644 pymusic/examples/message.py
 create mode 100755 pymusic/examples/messagelogger.py
 create mode 100755 pymusic/examples/messagesource.py
 create mode 100755 pymusic/examples/receivers.py
 create mode 100755 pymusic/examples/senders.py
 create mode 100644 pymusic/examples/test.music
 create mode 100755 pymusic/examples/testsink.py
 create mode 100755 pymusic/examples/testsource.py
 create mode 100644 pymusic/music/__init__.py
 create mode 100644 pymusic/music/music_c.h
 create mode 120000 pymusic/music/pybuffer.pxd
 create mode 120000 pymusic/music/pymusic.pxd
 create mode 100644 pymusic/music/pymusic_c.h
 create mode 100644 pymusic/pybuffer.cpp
 create mode 100644 pymusic/pybuffer.pxd
 create mode 100644 pymusic/pybuffer.pyx
 create mode 100644 pymusic/pymusic.cpp
 create mode 100644 pymusic/pymusic.pxd
 create mode 100644 pymusic/pymusic.pyx
 create mode 100644 pymusic/setup.py.in
 create mode 100644 rudeconfig/.gitignore
 create mode 100644 rudeconfig/AUTHORS
 create mode 100644 rudeconfig/COPYING
 create mode 100644 rudeconfig/ChangeLog
 create mode 100644 rudeconfig/Makefile.am
 create mode 100644 rudeconfig/NEWS
 create mode 100644 rudeconfig/README
 create mode 100644 rudeconfig/THANKS
 create mode 100644 rudeconfig/man3/rudeconfig.3
 create mode 100644 rudeconfig/src/AbstractData.cpp
 create mode 100644 rudeconfig/src/AbstractData.h
 create mode 100644 rudeconfig/src/AbstractOrganiser.cpp
 create mode 100644 rudeconfig/src/AbstractOrganiser.h
 create mode 100644 rudeconfig/src/AbstractParser.cpp
 create mode 100644 rudeconfig/src/AbstractParser.h
 create mode 100644 rudeconfig/src/AbstractWriter.cpp
 create mode 100644 rudeconfig/src/AbstractWriter.h
 create mode 100644 rudeconfig/src/Base64Encoder.cpp
 create mode 100644 rudeconfig/src/Base64Encoder.h
 create mode 100644 rudeconfig/src/Comment.cpp
 create mode 100644 rudeconfig/src/Comment.h
 create mode 100644 rudeconfig/src/ConfigImpl.cpp
 create mode 100644 rudeconfig/src/ConfigImpl.h
 create mode 100644 rudeconfig/src/DataLine.cpp
 create mode 100644 rudeconfig/src/DataLine.h
 create mode 100644 rudeconfig/src/File.cpp
 create mode 100644 rudeconfig/src/File.h
 create mode 100644 rudeconfig/src/KeyValue.cpp
 create mode 100644 rudeconfig/src/KeyValue.h
 create mode 100644 rudeconfig/src/ParserJuly2004.cpp
 create mode 100644 rudeconfig/src/ParserJuly2004.h
 create mode 100644 rudeconfig/src/RealOrganiser.cpp
 create mode 100644 rudeconfig/src/RealOrganiser.h
 create mode 100644 rudeconfig/src/Section.cpp
 create mode 100644 rudeconfig/src/Section.h
 create mode 100644 rudeconfig/src/SourceDest.cpp
 create mode 100644 rudeconfig/src/SourceDest.h
 create mode 100644 rudeconfig/src/WhiteSpace.cpp
 create mode 100644 rudeconfig/src/WhiteSpace.h
 create mode 100644 rudeconfig/src/Writer.cpp
 create mode 100644 rudeconfig/src/Writer.h
 create mode 100644 rudeconfig/src/config.cpp
 create mode 100644 rudeconfig/src/config.h
 create mode 100644 src/.gitignore
 create mode 100644 src/BIFO.cc
 create mode 100644 src/ChangeLog
 create mode 100644 src/FIBO.cc
 create mode 100644 src/Makefile.am
 create mode 100644 src/application_map.cc
 create mode 100644 src/application_mapper.cc
 create mode 100644 src/array_data.cc
 create mode 100644 src/clock.cc
 create mode 100644 src/collector.cc
 create mode 100644 src/configuration.cc
 create mode 100644 src/connection.cc
 create mode 100644 src/connectivity.cc
 create mode 100644 src/connector.cc
 create mode 100644 src/distributor.cc
 create mode 100644 src/error.cc
 create mode 100644 src/event_data.cc
 create mode 100644 src/event_router.cc
 create mode 100644 src/event_routing_map.cc
 create mode 100644 src/index_map.cc
 create mode 100644 src/index_map_factory.cc
 create mode 100644 src/interval.cc
 create mode 100644 src/ioutils.cc
 create mode 100644 src/linear_index.cc
 create mode 100644 src/memory.cc
 create mode 100644 src/multibuffer.cc
 create mode 100644 src/music-c-c.c
 create mode 100644 src/music-c.cc
 create mode 100644 src/music-c.h
 create mode 100644 src/music.hh
 create mode 100644 src/music/.gitignore
 create mode 100644 src/music/BIFO.hh
 create mode 100644 src/music/FIBO.hh
 create mode 100644 src/music/application_graph.hh
 create mode 100644 src/music/application_map.hh
 create mode 100644 src/music/application_mapper.hh
 create mode 100644 src/music/array_data.hh
 create mode 100644 src/music/clock.hh
 create mode 100644 src/music/collector.hh
 create mode 100644 src/music/communication.hh
 create mode 100644 src/music/configuration.hh
 create mode 100644 src/music/connection.hh
 create mode 100644 src/music/connectivity.hh
 create mode 100644 src/music/connector.hh
 create mode 100644 src/music/cont_data.hh
 create mode 100644 src/music/data_map.hh
 create mode 100644 src/music/debug.hh
 create mode 100644 src/music/distributor.hh
 create mode 100644 src/music/error.hh
 create mode 100644 src/music/event.hh
 create mode 100644 src/music/event_router.hh
 create mode 100644 src/music/event_routing_map.hh
 create mode 100644 src/music/index_map.hh
 create mode 100644 src/music/index_map_factory.hh
 create mode 100644 src/music/interval.hh
 create mode 100644 src/music/interval_table.hh
 create mode 100644 src/music/interval_tree.hh
 create mode 100644 src/music/ioutils.hh
 create mode 100644 src/music/linear_index.hh
 create mode 100644 src/music/memory.hh
 create mode 100644 src/music/message.hh
 create mode 100644 src/music/multibuffer.hh
 create mode 100644 src/music/music-config.hh.in
 create mode 100644 src/music/ordered_ilist.hh
 create mode 100644 src/music/parse.hh
 create mode 100644 src/music/permutation_index.hh
 create mode 100644 src/music/port.hh
 create mode 100644 src/music/predict_rank-c.h
 create mode 100644 src/music/predict_rank.hh
 create mode 100644 src/music/runtime.hh
 create mode 100644 src/music/sampler.hh
 create mode 100644 src/music/scheduler.hh
 create mode 100644 src/music/scheduler_agent.hh
 create mode 100644 src/music/setup.hh
 create mode 100644 src/music/spatial.hh
 create mode 100644 src/music/spikes.hh
 create mode 100644 src/music/subconnector.hh
 create mode 100644 src/music/temporal.hh
 create mode 100644 src/music/version.hh.in
 create mode 100644 src/parse.cc
 create mode 100644 src/permutation_index.cc
 create mode 100644 src/port.cc
 create mode 100644 src/predict_rank-c.cc
 create mode 100644 src/predict_rank.cc
 create mode 100644 src/runtime.cc
 create mode 100644 src/sampler.cc
 create mode 100644 src/scheduler.cc
 create mode 100644 src/scheduler_agent.cc
 create mode 100644 src/setup.cc
 create mode 100644 src/spatial.cc
 create mode 100644 src/subconnector.cc
 create mode 100644 src/temporal.cc
 create mode 100644 src/version.cc
 create mode 100644 testsuite/.gitignore
 create mode 100644 testsuite/Makefile.am
 create mode 100644 testsuite/music_tests.sh.in
 create mode 100644 testsuite/sanitytests/.gitignore
 create mode 100644 testsuite/sanitytests/Makefile.am
 create mode 100644 testsuite/sanitytests/chain.test
 create mode 100644 testsuite/sanitytests/clocksource.cc
 create mode 100644 testsuite/sanitytests/cloop.test
 create mode 100644 testsuite/sanitytests/const.test
 create mode 100644 testsuite/sanitytests/constsource.cc
 create mode 100644 testsuite/sanitytests/contclock.test
 create mode 100644 testsuite/sanitytests/contdelay.cc
 create mode 100644 testsuite/sanitytests/divergence.test
 create mode 100644 testsuite/sanitytests/eventdelay.cc
 create mode 100755 testsuite/sanitytests/events.test
 create mode 100644 testsuite/sanitytests/fork.test
 create mode 100644 testsuite/sanitytests/launchtest.cc
 create mode 100644 testsuite/sanitytests/launchtest.test
 create mode 100644 testsuite/sanitytests/loop.test
 create mode 100644 testsuite/sanitytests/messages.test
 create mode 100644 testsuite/sanitytests/multicomm.test
 create mode 100644 testsuite/sanitytests/multiport.cc
 create mode 100644 testsuite/sanitytests/multiport.test
 create mode 100644 testsuite/sanitytests/run_test
 create mode 100644 testsuite/test_old/ChangeLog
 create mode 100644 testsuite/test_old/chain.music
 create mode 100644 testsuite/test_old/cloop.music
 create mode 100644 testsuite/test_old/coba.cc
 create mode 100644 testsuite/test_old/const.music
 create mode 100644 testsuite/test_old/contclock.music
 create mode 100644 testsuite/test_old/divergence.music
 create mode 100644 testsuite/test_old/events.music
 create mode 100644 testsuite/test_old/events.py
 create mode 100644 testsuite/test_old/fork.music
 create mode 100644 testsuite/test_old/launcher.cc
 create mode 100644 testsuite/test_old/launchtest.music
 create mode 100644 testsuite/test_old/loop.music
 create mode 100644 testsuite/test_old/multicomm.music
 create mode 100644 testsuite/test_old/multipoisson.music
 create mode 100644 testsuite/test_old/multipoisson2.music
 create mode 100644 testsuite/test_old/multiport.music
 create mode 100644 testsuite/test_old/parsetest.cc
 create mode 100644 testsuite/test_old/poisson.music
 create mode 100644 testsuite/test_old/poisson2.music
 create mode 100644 testsuite/unittests/catch/.gitignore
 create mode 100644 testsuite/unittests/catch/Makefile.am
 create mode 100644 testsuite/unittests/catch/catch.hpp
 create mode 100644 testsuite/unittests/catch/test_ag.cc
 create mode 100644 utils/.gitignore
 create mode 100644 utils/ChangeLog
 create mode 100644 utils/Makefile.am
 create mode 100644 utils/VisualiseNeurons.cpp
 create mode 100644 utils/VisualiseNeurons.h
 create mode 100644 utils/contsink.cc
 create mode 100644 utils/datafile.cc
 create mode 100644 utils/datafile.h
 create mode 100644 utils/eventcounter.cc
 create mode 100644 utils/eventgenerator.cc
 create mode 100644 utils/eventlogger.cc
 create mode 100644 utils/eventselect.cc
 create mode 100644 utils/eventsink.cc
 create mode 100644 utils/eventsource.cc
 create mode 100644 utils/messagesource.cc
 create mode 100644 utils/music.cc
 create mode 100644 utils/viewevents.cpp

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..493aae5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+*.in
+*.lo
+*.la
+
+config.*
+
+Makefile
+
+/aclocal.m4
+/configure
+/depcomp
+/install-sh
+/libtool
+/ltmain.sh
+/missing
+/py-compile
+/stamp-h1
+
+/autom4te.cache/
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..4b28183
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,11 @@
+To find out what should go in this file, see "Information For
+Maintainers of GNU Software" (maintain.texi), the section called
+"Recording Changes".
+
+Mikael Djurfeldt <mikael@djurfeldt.com>
+
+Örjan Ekeberg
+
+Johannes Hjorth wrote the viewevents utility.
+
+Eilif Müller added support for MPICH 2.0
diff --git a/BUGS b/BUGS
new file mode 100644
index 0000000..2ded365
--- /dev/null
+++ b/BUGS
@@ -0,0 +1,3 @@
+This is the list of known MUSIC bugs:
+
+* MUSIC does not yet run on heterogenous clusters.
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+                    GNU 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.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU 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
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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, either version 3 of the License, or
+    (at your option) any later version.
+
+    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 should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..3ecb5e4
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,205 @@
+2014-07-22  Ekaterina Brocke  <brocke@kth.se>
+
+	* Version 1.1.15
+
+2014-07-21  Mikael Djurfeldt  <mdj@jessie.pdc.kth.se>
+
+	* Version 1.1.14
+
+2014-07-21  Mikael Djurfeldt  <mdj@vm-xubuntu-12.04.4>
+
+	* Version 1.1.13
+
+2014-07-17  Mikael Djurfeldt  <mdj@jessie.pdc.kth.se>
+
+	* Version 1.1.12
+
+2014-07-16  Mikael Djurfeldt  <mdj@jessie.pdc.kth.se>
+
+	* Version 1.1.11
+
+2013-07-11  Mikael Djurfeldt  <mdj@wand.pdc.kth.se>
+
+	* Version 1.1.9
+
+2012-09-20  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Version 1.1.8
+
+	* configure.ac: New configuration options --enable-isend,
+	--enable-anysource.
+
+2012-08-24  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* PORTING: New file.
+
+2012-08-23  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Version 1.1.7
+
+2012-08-22  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Version 1.1.6
+
+2012-08-21  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Version 1.1.5
+
+2012-08-20  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Version 1.1.3
+
+2012-08-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Version 1.1.2
+
+2012-08-07  Mikael Djurfeldt  <mdj@ubuntu-11.10>
+
+	* Version 1.1.1
+
+2012-08-03  Mikael Djurfeldt  <mdj@ubuntu-11.10>
+
+	* configure.ac: Updated to version 1.1.0.
+
+	* configure.ac: Generate music/version.hh.in.
+
+2012-03-15  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac (AM_PATH_PYTHON): Added.
+
+	* music: New directory. Python interface for configuring MUSIC.
+
+2012-01-30  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Make sure that MPI libraries are listed at the end
+	of the command line in AC_CHECK_FUNCS.
+
+2011-03-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Support for Cray XE6.
+
+2010-07-28  Mikael Djurfeldt  <mdj@djurfeldt.com>
+
+	* Release 1.0.7
+
+2009-10-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.6
+
+2009-10-24  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.5
+
+2009-10-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Support for MPICH 2 (Thanks to Eilif Müller.)
+
+2009-04-01  Mikael Djurfeldt  <djurfeldt@nada.kth.se>
+
+	* Release 1.0.4
+
+2009-03-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.3
+
+2009-03-12  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.2
+
+2009-03-11  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Added AM_MAINTAINER_MODE.
+
+2009-03-09  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am (debian-source): Copy manual source into debian
+	source tree.
+
+2009-03-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.1
+
+	* configure.ac (CXXFLAGS): Added -pedantic -Wall -Wno-long-long.
+
+2009-03-07  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Renamed package to incf-music (since people in the
+	Debian community has complained about the too generic package
+	name).
+
+2009-03-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am (EXTRA_DIST): Added debian subdirectory to
+	distribution.
+
+2009-03-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0
+
+2009-02-11  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* mpidep: New directory for MPI dependent code.
+
+	* configure.ac: Generate mpidep/Makefile.
+
+	* configure.ac: Test if ompi_comm_free exists instead of
+	ompi_comm_create which doesn't exist in OpenMPI 1.3.
+
+	* configure.ac: Pass variables to be substituted one-by-one to
+	AC_SUBST.
+
+2008-11-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac (OPTIONAL_UTILS): New variable.  Add viewevents
+	conditionally depending on existence of GL/glut.h.
+
+2008-10-16  Mikael Djurfeldt  <mikael@moritz-heliass-macbook.local>
+
+	* configure.ac: Use $CXX instead of $MPI_CXX in tests for
+	configuration of MPI implementation dependent code.
+
+2008-09-23  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Setup MPI_C; Test for MPI::Init_thread.
+
+2007-11-07  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Don't try to build shared libraries on BGL.
+
+	* autogen.sh, aclocal.sh: Suppress error messages from which.
+
+2007-11-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Rewritten to make better use of AC_PROG_CXX; Logic
+	added to manage subdirectory rudeconfig directly (tests moved from
+	original rudeconfig configure.ac).
+
+2007-11-02  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Test for ompi_comm_create (used to identify
+	OPENMPI); Moved configuration of rudeconfig to beginning.
+
+	* Makefile.am (SUBDIRS): Added rudeconfig.
+
+2007-11-01  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Added AC_CONFIG_SUBDIRS(rudeconfig).
+
+	* rudeconfig: Added.
+
+2007-10-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Added test for rts_get_personality; Generate
+	utils/Makefile.
+
+	* Makefile.am (SUBDIRS): Added utils.
+
+2007-10-18  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configure.ac: Introduced guessing of host MPI framework. Handle
+	openmpi version of mpiCC.
+
+2007-09-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* AUTHORS, COPYING, INSTALL, NEWS, README, ChangeLog,
+	configure.ac, Makefile.am, autogen.sh, aclocal.sh: New files
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..5458714
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,234 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..4778d85
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,33 @@
+SUBDIRS = mpidep rudeconfig src utils @TESTDIR@ @EXTRAS@ doc @EXAMPLESDIR@ @PYMUSIC_SUBDIR@
+
+debdir=../@PACKAGE_NAME@-@PACKAGE_VERSION@
+
+debian-source: dist
+	mv @PACKAGE_NAME@-@PACKAGE_VERSION@.tar.gz ../@PACKAGE_NAME@_@PACKAGE_VERSION@.orig.tar.gz
+	@test ! -e $(debdir) || ( echo "*** Remove directory ../@PACKAGE_NAME@-@PACKAGE_VERSION@" && exit 1 )
+	( cd ..; tar zxf @PACKAGE_NAME@_@PACKAGE_VERSION@.orig.tar.gz )
+	mkdir $(debdir)/debian
+	cp -p debian/* $(debdir)/debian
+	cp -p doc/music-manual.tex doc/music-rfc.bib doc/music-c-int.h $(debdir)/doc
+	mkdir $(debdir)/doc/figures
+	cp -p doc/figures/*.asy $(debdir)/doc/figures
+
+EXTRA_DIST = BUGS
+
+#dist-hook:
+#	rm $(distdir)/TODO
+installcheck-local:
+if LAUNCHSTYLE_SET
+	/bin/sh $(DESTDIR)$(bindir)/music_tests.sh
+else
+	@echo "checkinstall target is supported only when compiled with openMPI or MPICH libraries."
+	@exit 1
+endif
+
+
+
+distuninstallcheck:
+        @:
+
+#uninstall:
+#	@echo "make: uninstall target is not supported."
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..a034dec
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,92 @@
+MUSIC NEWS --- history of user-visible changes.
+Copyright (C) 2009, 2010 INCF
+
+Please send MUSIC bug reports to music-bugs@incf.org.
+
+
+Changes in 1.0.7:
+
+* music library
+
+** Bug fix release.
+
+
+Changes in 1.0.6:
+
+* music library
+
+** Fixes for GCC version 4.4.
+
+** Don't include RPATH in libmusic.so.
+
+
+Changes in 1.0.5:
+
+* music library
+
+** Optimizations of event routing.  MUSIC now discovers ranges of
+   indices which can be handled collectively by one entry in the event
+   router, even in the case that this is not apparent from index maps
+   but due to the effect of negotiations with the port connected on
+   the other side.
+
+** Bug fixes.
+   
+
+Changes in 1.0.4:
+
+* test directory
+
+** New example: messages.music
+
+* music library
+
+** Message ports now work correctly.
+
+** Optimizations.
+
+
+Changes in 1.0.3:
+
+* music library
+
+** Fixes a bug which occurs in Runtime::finalize () when using the
+   threading version of the Setup constructor under OpenMPI 1.2.7.
+
+** Other smaller fixes.
+
+
+Changes in 1.0.2:
+
+* music library
+
+** Better error reporting.
+
+** Bug fixes.
+
+** New README file in test directory.
+
+** New demo in test directory.
+
+
+Changes in 1.0.1:
+
+* music utility
+
+** Bug fixes
+
+** Improved error reporting
+
+** New option '-m' prints application rank mapping
+
+** New option '-v' prints version information
+
+** Debian packaging support
+
+
+First release: 1.0
+
+Local variables:
+mode: outline
+paragraph-separate: "[ 	]*$"
+end:
diff --git a/PORTING b/PORTING
new file mode 100644
index 0000000..01a81ec
--- /dev/null
+++ b/PORTING
@@ -0,0 +1,78 @@
+When porting music to a new machine, the following things needs to be
+taken into consideration:
+
+
+1. Regeneration of the configure script
+
+The script ./autogen.sh is used to generate/regenerate the configure
+script. For this to work, the GNU autotools (autoconf, automake and
+libtool) need to be installed.
+
+
+2. Compilation and linking flags
+
+configure.ac contains mechanisms which try to identify which MPI
+implementation/environment is in use and, based on this, decide
+automagically which compiler, compilation flags and linking flags to
+use. To circumvent, pass variable definitions ro configure, e.g.:
+
+  ./configure MPI_CXXFLAGS="-g -O3 -Wall -pedantic"
+
+The variables are:
+
+MPI_CXX       The compiler to use for MPI code
+MPI_CXXFLAGS  C++ compilation flags
+MPI_CFLAGS    C compilation flags
+MPI_LDFLAGS   Linking flags
+
+
+3. MPI implementation dependent code
+
+MUSIC depends on two MPI implementation dependent functions: getRank,
+which predicts the rank a process is going to be assigned when
+executing MPI_Init, and getConfig, which determines the first command
+line argument to the music launch utility "music" (also before having
+executed MPI_Init.
+
+
+4. Alternative launch method
+
+On some computers, the standard MUSIC launch method (using the music
+utility) does not work, either because it is difficult to supply an
+implementation of the functions mention under point 3 above, or
+because the compute node OS does not support the system call execvp
+used by the music launch utility to replace its image with one of the
+binaries in the multi-simulation.
+
+In such cases, it is possible to launch the multi-simulation as an
+MPMD/MIMD program. Example: If we have a MUSIC configuration file
+myconfig.music, defining two applications named A and B, the standard
+way to launch the multi-simulation is:
+
+  mpirun -np N music myconfig.music
+
+where N is the number of processes needed (as specified in
+myconfig.music) by the multi-simulation. Using the alternative method,
+one first issues the command line:
+
+  music -e myconfig.music
+
+This will write one shell script per application into the current
+working directory, in this case A.sh and B.sh. These scripts can then
+by used to launch the multi-simulation. Under OpenMPI, the command
+line would be:
+
+  mpirun -np NA A.sh : -np NB B.sh
+
+where NA and NB are the number of processes needed (and specified in
+myconfig.music) by the applications A and B respectively.
+
+On a machine where the architecture of the login node differs from the
+architecture of the compute nodes, it is sometimes convenient to be
+able to compile the music launch utility without MPI support on the
+login node in order to be able to use the -e option. This is
+convenient, for example if the login node is running a script which
+prepares jobs to be executed on the compute nodes.  If you need to do
+this, MUSIC can be configured without MPI:
+
+  ./configure --disable-mpi
diff --git a/README b/README
new file mode 100644
index 0000000..642a3f1
--- /dev/null
+++ b/README
@@ -0,0 +1,111 @@
+* What is MUSIC?
+
+MUSIC is an API allowing large scale neuron simulators using MPI
+internally to exchange data during runtime.  MUSIC provides mechanisms
+to transfer massive amounts of event information and continuous values
+from one parallel application to another.  Special care has been taken
+to ensure that existing simulators can be adapted to MUSIC.  In
+particular, MUSIC handles data transfer between applications that use
+different time steps and different data allocation strategies.
+
+This is the MUSIC pilot implementation.
+
+The two most important components built from this software
+distribution is the music library `libmusic.a' and the music utility
+`music'.  A MUSIC-aware simulator links against the C++ library and
+can be launched using mpirun together with the music utility as
+described below.  MUSIC can also be used from a C program using the
+API in music-c.h.
+
+MUSIC is distributed under the GNU General Public License v3.
+
+
+* Required external packages
+
+MUSIC is written in C++ and makes use of the MPI message passing
+library.  MUSIC has been tested with versions 1.2 and 1.3 of OpenMPI,
+mpich and on BG/L.  A visualization tool `viewevents' can be built if
+the GLUT toolkit is installed.
+
+MUSIC version 1.0 makes use of the "long long" data type supported by,
+for example, the GNU C++ compiler g++.
+
+
+* Getting started
+
+MUSIC can be built and installed using the generic installation
+instructions found in the file INSTALL.  At the top of the source
+distribution directory, do:
+
+./configure
+make
+make install
+
+(On some UNIX distributions you might need to run `ldconfig' or define
+LD_LIBRARY_PATH:
+
+  export LD_LIBRARY_PATH=/usr/local/lib
+
+for the music utility to find its library.)
+
+A MUSIC multisimulation is specified in a configuration file given as
+the first argument to the music utility.  The test subdirectory
+contains a collection of examples, for example:
+
+cd test
+mpirun -np 4 /usr/local/bin/music demo.music
+
+
+* Compilation and linking flags
+
+configure.ac contains mechanisms which try to identify which MPI
+implementation/environment is in use and, based on this, decide
+automagically which compiler, compilation flags and linking flags to
+use. To circumvent, pass variable definitions ro configure, e.g.:
+
+  ./configure MPI_CXXFLAGS="-g -O3"
+
+The variables are:
+
+MPI_CXX       The compiler to use for MPI code
+MPI_CXXFLAGS  C++ compilation flags
+MPI_CFLAGS    C compilation flags
+MPI_LDFLAGS   Linking flags
+
+
+* Porting
+
+When launching a set of applications in a multisimulation, MUSIC needs
+to go outside the MPI standard in two respects:
+
+1. It needs to know the MPI process rank of the running process before
+calling MPI::Init.
+
+2. It needs to extract the first argument given to the music utility
+before calling MPI::Init.
+
+The configuration script tries to figure out which MPI distribution is
+installed and how to compiler MUSIC for that distribution.  The
+subdirectory mpidep contains all non-standard code.  If you are trying
+to port the MUSIC library to a new version of MPI, please supply new
+definitions for the functions getRank and getConfig in
+mpidep/mpidep.c.  For more details, see the file PORTING in this
+directory.
+
+
+* Where to find more information
+
+The MUSIC manual and other information can be found on the MUSIC home
+page at the INCF Software Center:
+
+  http://software.incf.org/software/music/home
+
+Questions and requests can be sent to music-project@incf.org
+
+
+* Submitting bug reports
+
+Bug reports can be sent to music-bugs@incf.org
+
+Please refer to the MUSIC home page at the INCF software center with
+the URL given in the previous section.
diff --git a/RELEASE b/RELEASE
new file mode 100644
index 0000000..7fb513d
--- /dev/null
+++ b/RELEASE
@@ -0,0 +1,25 @@
+Checklist for a release:
+
+* AC_INIT in configure.ac
+
+* (optional) debian/changelog
+
+* update NEWS
+
+* version number in README
+
+* "Release x.y.z" in all ChangeLog:s except in rudeconfig/
+
+* make debian-source
+
+* cd ../music_x.y.z
+
+* dpkg-buildpackage -rfakeroot
+
+* lintian -i music_x.y.z.-n_ARCH.changes
+
+* dupload music_x.y.z.-n_ARCH.changes
+
+* svn commit
+
+* svn cp http://svn.incf.org/svn/music/trunk http://svn.incf.org/svn/music/tags/release-x.y.z -m 'Tagging release x.y.z of MUSIC'
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..a59fc79
--- /dev/null
+++ b/TODO
@@ -0,0 +1,105 @@
+Things to do in preparation for the music-1.2.0 release:
+--- Start music-1.2.0
+
+* E: Make testsuite
+
+* E: (If sufficient time): Better multiconnector communicator creation
+  algorithm
+
+* M: Complete multiconnector implementation (support for abitrary
+  number of apps)
+
+* M: Complete Python bindings
+
+* Test that continuous ports work as expected
+
+** Interpolation/non-interpolated case, also with different buffering
+   and different ITI (inter-tick-interval) for the communication
+   applications.
+
+* Better README
+
+* Update NEWS
+
+* Update manual (/doc) with new configuration file syntax
+
+--- End music-1.2.0
+
+* OrderedIList should be made more generic and handle insertion of
+  indices which already exist in the ilist
+
+* remove ProxyConnector?
+
+* remove multiComm member?
+
+* remove leader and nProcs info in scheduler Nodes:s?
+
+* checkpointing
+
+* use duplicate of MPI::COMM_WORLD for setting up inter-communicators
+
+* report error if index maps overlap on the sender side
+
+* for the event router only: join intervals also over "holes" in the
+  local index map
+
+* duplicate COMM_WORLD and use that throughout library?
+
+* error handling (call MPI error handler)
+
+* revise timing algorithm to allow for loops with 1 tick acceptable
+  latency where this is theoretically possible.
+
+* connector signature checking when connecting to peers (cont ports:
+  common MPI data types + unknown + size)
+
+* Check that all administrative objects get deallocated at start of runtime
+  (for example the objects assoicated with configuration)
+
+* lift out as much as possible of the negotiation stuff from
+  connectors and move to connections, for example ConnectorInfo and
+  createIntercomm
+
+* rename Runtime::schedule
+
+* report port name if missing
+
+* alternative implementation for clockstate (not long long)
+
+* Code duplication sampler - distributor - collector - kommentarer
+
+* optional arguments when mapping ports: maxbuffered but not latency
+   
+* error message if latency => > maxBuffered
+   
+* indexinterval::local --> offset
+
+* Use pass-by-reference instead of pass-by-value where possible
+  (especially for some strings)
+
+* cleanup constructor arguments in subconnector.cc
+
+* marshalling, for example in temporal.cc, subconnector.cc
+
+* Documentation strings
+
+Optional
+  
+* Improve all error reporting (giving more informative messages with names etc)
+
+* Set flags with options to the music utility and transmit them to the
+  applications so that library behavior can be controlled.  E.g.,
+  print out run statistics, such as part of time spent in tick() when
+  deleting runtime.
+
+* Join intervals in PermutationIndex and IndexMapFactory
+
+* Th mpidep directory should contain a test binary which is
+  built and run before anything else is being compiled
+
+* Write piecewise_linear_index and derive linear_index and
+  permutation_index from it.
+
+* Communicate between ticks using non-blocking communication.
+  Possible to have two kinds of subconnectors, keeping the current
+  ones for cases with short acceptable latency,
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..d4d2cc6
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,70 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
+#
+# DESCRIPTION
+#
+#   Check whether the given FLAG works with the current language's compiler
+#   or gives an error.  (Warnings, however, are ignored)
+#
+#   ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+#   success/failure.
+#
+#   If EXTRA-FLAGS is defined, it is added to the current language's default
+#   flags (e.g. CFLAGS) when the check is done.  The check is thus made with
+#   the flags: "CFLAGS EXTRA-FLAGS FLAG".  This can for example be used to
+#   force the compiler to issue an error when a bad flag is given.
+#
+#   NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+#   macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#   Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+#   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, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   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 should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+  ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+  _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+  AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+    [AS_VAR_SET(CACHEVAR,[yes])],
+    [AS_VAR_SET(CACHEVAR,[no])])
+  _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+  [m4_default([$2], :)],
+  [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/aclocal.sh b/aclocal.sh
new file mode 100755
index 0000000..535d338
--- /dev/null
+++ b/aclocal.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+if test -z "$ACLOCAL" ; then
+ for each in aclocal-1.10 aclocal-1.9 aclocal-1.8 aclocal-1.7 aclocal-1.6 aclocal ; do
+   ACLOCAL=$each
+   if test -n "`which $each 2>/dev/null`" ; then break ; fi
+ done
+fi
+
+ACDIR=`which $ACLOCAL`
+ACDIR=`dirname $ACDIR`
+ACDIR=`dirname $ACDIR`/share/aclocal
+
+for each in $ACDIR ; do
+  if test -d "$each"  ; then 
+    AFLAGS="-I $each $AFLAGS"
+  fi
+done
+
+echo $ACLOCAL $AFLAGS $@
+$ACLOCAL $AFLAGS $@
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..a28ea75
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+[ -f autogen.sh ] || {
+  echo "autogen.sh: run this command only at the top of the source tree."
+  exit 1
+}
+
+if test -z "$AUTOMAKE" ; then
+ for each in automake-1.10 automake-1.9 automake-1.8 automake-1.7 automake-1.6 automake ; do
+   AUTOMAKE=$each
+   if test -n "`which $each 2>/dev/null`" ; then break ; fi
+ done
+fi
+
+./aclocal.sh &&
+echo libtoolize --copy --automake &&
+libtoolize --copy --automake &&
+echo autoheader &&
+autoheader &&
+echo autoconf &&
+autoconf &&
+echo $AUTOMAKE --copy --add-missing &&
+$AUTOMAKE --copy --add-missing &&
+echo Now run configure and make.
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..1d551fd
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,406 @@
+dnl Process this file with autoconf to produce configure.
+AC_INIT(music, 1.1.15)
+AM_INIT_AUTOMAKE
+AM_CONFIG_HEADER([config.h])
+AM_MAINTAINER_MODE
+
+if test "$MPI_CXX" != ""; then
+  CXX="$MPI_CXX"
+fi
+
+AC_PROG_CXX([mpiCC mpixlcxx mpixlcxx_r mpicxx CC])
+MPI_CXX="$CXX"
+
+AC_MSG_CHECKING([which MPI system we think we are using])
+case "$MPI_CXX" in
+  mpiCC)
+    changequote({, })
+    MPI_C=mpicc
+    if $MPI_CXX -compile_info >/dev/null 2>/dev/null; then
+      SYSGUESS=mpich
+      CXX="`$MPI_CXX -compile_info | sed -e 's/^\([^ ]*\).*/\1/'`"
+    else
+      #	mpiCC can be a C compiler under OpenMPI
+      if mpicxx -showme >/dev/null 2>/dev/null; then
+        SYSGUESS=openmpi
+        CXX="`mpicxx -showme | sed -e 's/^\([^ ]*\).*/\1/'`"
+      else
+        changequote([, ])      
+        AC_MSG_ERROR([
+Confused when trying to determine MPI_CXX, MPI_CXXFLAGS etc.
+Please set them manually.])
+        changequote({, })
+      fi
+    fi
+    LAUNCHSTYLE=_mpirun
+    TESTDIR=testsuite
+    EXTRAS=extras
+    changequote([, ])
+    ;;
+  mpixlcxx_r)
+    MPI_C=mpixlc_r
+    SYSGUESS=bgp
+    CXX="$MPI_CXX"
+    #CC="`echo $MPI_CXX | sed -e 's/xlcxx$/xlc/;s/cxx$/cc/'`"
+    CC="$MPI_C"
+    ;;
+  mpixlcxx)
+    MPI_C=mpixlc
+    SYSGUESS=bgq
+    CXX="$MPI_CXX"
+    #CC="`echo $MPI_CXX | sed -e 's/xlcxx$/xlc/;s/cxx$/cc/'`"
+    CC="$MPI_C"
+    ;;
+  mpicxx)
+    MPI_C=mpicc
+    CC="$MPI_C"
+    CXX="$MPI_CXX"
+    if mpich2version >/dev/null 2>/dev/null; then
+       SYSGUESS=mpich2
+       AC_DEFINE(HAVE_MPICH2, 1, [Define to 1 if you have MPICH2.])
+    else
+       SYSGUESS=bgl
+    fi
+    ;;
+  CC)
+    # We should be checking MPI version but for the Cray we do it differently
+    if uname -r | grep -q cray_gem_s; then
+      SYSGUESS=cray_xe6
+      AC_DEFINE(CRAY_XE6, 1, [Define if this is a Cray XE6 system.])
+      CC=cc
+      CXX=CC
+    else
+      SYSGUESS=unknown
+    fi
+    ;;
+  xlC)
+    MPI_C=xlc
+    SYSGUESS=bgq_seq
+    CXX="$MPI_CXX"
+    CC="$MPI_C"
+    ;;
+
+  *)
+    SYSGUESS=unknown
+    ;;
+esac
+echo "SYSGUESS=$SYSGUESS"
+
+AC_MSG_CHECKING(MPI_CXXFLAGS)
+if test "$MPI_CXXFLAGS" != ""; then
+  echo "$MPI_CXXFLAGS"
+else
+  case "$SYSGUESS" in
+    mpich|mpich2)
+      changequote(<, >)
+      MPI_CXXFLAGS="`$MPI_CXX -compile_info | sed -e 's/^[^ ]* //;s/ -c / /'`"
+      changequote([, ])
+      ;;
+    openmpi)
+      MPI_CXXFLAGS="`mpicxx -showme:compile`"
+      ;;
+    bgp)
+      MPI_CXXFLAGS="-qarch=450 -qtune=450 -qhot -qnostrict"
+      enable_shared=no
+      ;;
+    bgq)
+      MPI_CXXFLAGS="-qarch=qp -qtune=qp -qhot -qnostrict"
+      enable_shared=no
+      ;;
+    cray_xe6)
+      MPI_CXXFLAGS=""
+      ;;
+    bgq_seq)
+      MPI_CXXFLAGS=""
+      enable_shared=no
+      ;;
+    *)
+      AC_MSG_ERROR([
+Could not determine proper value for MPI_CXXFLAGS.  Please see README.])
+      ;;
+  esac
+  echo "$MPI_CXXFLAGS"
+fi
+
+AC_MSG_CHECKING(MPI_CFLAGS)
+if test "$MPI_CFLAGS" != ""; then
+  echo "$MPI_CFLAGS"
+else
+  case "$SYSGUESS" in
+    mpich|mpich2)
+      changequote(<, >)
+      MPI_CFLAGS="`$MPI_C -compile_info | sed -e 's/^[^ ]* //;s/ -c / /'`"
+      changequote([, ])
+      ;;
+    openmpi)
+      MPI_CFLAGS="`mpicc -showme:compile`"
+      ;;
+    bgp)
+      MPI_CFLAGS="-qarch=450 -qtune=450 -qhot -qnostrict"
+      enable_shared=no
+      ;;
+    bgq)
+      MPI_CFLAGS="-qarch=qp -qtune=qp -qhot -qnostrict"
+      enable_shared=no
+      ;;
+    cray_xe6)
+      MPI_CFLAGS=""
+      ;;
+    bgq_seq)
+      MPI_CFLAGS=""
+      enable_shared=no
+      ;;
+    *)
+      AC_MSG_ERROR([
+Could not determine proper value for MPI_CFLAGS.  Please see README.])
+      ;;
+  esac
+  echo "$MPI_CFLAGS"
+fi
+
+AC_MSG_CHECKING(MPI_LDFLAGS)
+if test "$MPI_LDFLAGS" != ""; then
+  echo "$MPI_LDFLAGS"
+else
+  case "$SYSGUESS" in
+    mpich|mpich2)
+      changequote(<, >)
+      MPI_LDFLAGS="`$MPI_CXX -link_info | sed -e 's/^[^ ]* //;s/ -c / /'`"
+      changequote([, ])
+      ;;
+    openmpi)
+      MPI_LDFLAGS="`mpicxx -showme:link`"
+      ;;
+    bgp|bgq|cray_xe6|bgq_seq)
+      MPI_LDFLAGS=""
+      ;;
+    *)
+      AC_MSG_ERROR([
+Could not determine proper value for MPI_LDFLAGS.  Please see README.])
+      ;;
+  esac
+  echo "$MPI_LDFLAGS"
+fi
+
+CXXFLAGS="-g -O3"
+
+#if test "$ac_test_CXXFLAGS" != set; then
+#  if test "$CXXFLAGS" = "-O2"; then
+#    CXXFLAGS="-O3"
+#  else
+  #  CXXFLAGS="-O2"
+#    CXXFLAGS="-g -O0"
+if test $CXX = g++; then
+	CXXFLAGS="-pedantic -Wall -Wno-long-long $CXXFLAGS"
+fi
+#  fi
+#fi
+
+AM_PATH_PYTHON
+AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != :])
+
+AC_PROG_CC
+AC_PROG_LIBTOOL
+
+dnl Checks for rudeconfig:
+AC_HEADER_STDC
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_SIZE_T
+AC_CHECK_TYPES([long long])
+
+AC_CHECK_FUNCS([strrchr mallinfo])
+
+dnl Other checks
+OPTIONAL_UTILS=""
+AC_CHECK_HEADER([GL/glut.h], OPTIONAL_UTILS+="viewevents ")
+
+AC_LANG_PUSH(C++)
+save_CXX="$CXX"
+save_LIBS="$LIBS"
+dnl Must use $CXX, not $MPI_CXX, here
+
+CXX="$CXX $MPI_CXXFLAGS"
+LIBS="$LIBS $MPI_LDFLAGS"
+AC_CHECK_FUNCS([rts_get_personality ompi_comm_free])
+
+AC_MSG_CHECKING([for MPI::Init_thread method])
+ac_have_cxx_mpi_init_thread=no
+AC_COMPILE_IFELSE(
+  [AC_LANG_SOURCE([
+#include <mpi.h>
+int main (int argc, char **argv)
+{
+  int res = MPI::Init_thread (argc, argv, 0);
+}
+])],
+AC_DEFINE(HAVE_CXX_MPI_INIT_THREAD, 1, [Define to 1 if you have the MPI::Init_thread method])
+ac_have_cxx_mpi_init_thread=yes
+)
+AC_MSG_RESULT($ac_have_cxx_mpi_init_thread)
+
+AC_ARG_ENABLE(mpi,
+              [  --disable-mpi           disable mpi support],
+              MUSIC_USE_MPI="$enableval", MUSIC_USE_MPI="yes")
+if test $MUSIC_USE_MPI = yes ; then 
+  MUSIC_USE_MPI=1
+  MPI_UTILS="eventsource eventsink eventselect eventgenerator eventcounter eventlogger contsink messagesource"
+  EXAMPLESDIR="examples"
+else
+  MUSIC_USE_MPI=0
+  MPI_UTILS=""
+  OPTIONAL_UTILS=""
+  EXAMPLESDIR=""
+fi
+AC_ARG_ENABLE(isend,
+              [  --disable-isend          disable isend],
+              MUSIC_ISENDWAITALL="$enableval", MUSIC_ISENDWAITALL="yes")
+if test $MUSIC_ISENDWAITALL = yes ; then 
+  MUSIC_ISENDWAITALL=1
+else
+  MUSIC_ISENDWAITALL=0
+fi
+AC_ARG_ENABLE(anysource,
+              [  --disable-anysource      disable any source receive],
+              MUSIC_ANYSOURCE="$enableval", MUSIC_ANYSOURCE="yes")
+if test $MUSIC_ANYSOURCE = yes ; then 
+  MUSIC_ANYSOURCE=1
+else
+  MUSIC_ANYSOURCE=0
+fi
+
+LIBS="$save_LIBS"
+CXX="$save_CXX"
+AC_LANG_POP(C++)
+
+if test $ac_cv_type_size_t = yes; then
+  MUSIC_HAVE_SIZE_T=1
+else
+  MUSIC_HAVE_SIZE_T=0
+fi
+
+if test $ac_cv_type_long_long = yes; then
+  MUSIC_HAVE_LONG_LONG=1
+else
+  MUSIC_HAVE_LONG_LONG=0
+fi
+
+if test "$prefix" = NONE; then
+   PKGDATADIR=`eval echo $ac_default_prefix/share/$PACKAGE-$PACKAGE_VERSION`
+else
+   PKGDATADIR=`eval echo $prefix/share/$PACKAGE-$PACKAGE_VERSION`
+fi
+
+if test "$prefix" = NONE; then
+   PKGEXTRABINDIR=`eval echo $ac_default_prefix/lib/$PACKAGE-$PACKAGE_VERSION`
+else
+   PKGEXTRABINDIR=`eval echo $prefix/lib/$PACKAGE-$PACKAGE_VERSION`
+fi
+
+#TEST_SH_LIST=${srcdir}/*.test
+
+AC_ARG_WITH([python],
+    [AS_HELP_STRING([--without-python], [ignore the presence of Python and disable PyMUSIC])])
+
+AS_IF([test "x$with_python" != "xno"],
+      [AM_PATH_PYTHON([2.6], [have_python=yes], [have_python=no])],
+      [have_python=no])
+
+AS_IF([test "x$have_python" = "xyes"], [
+    PYTHON_INC=`$PYTHON -c 'import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_python_inc())'`
+    AC_CHECK_FILE(["${PYTHON_INC}/Python.h"], 
+    		  [PYMUSIC_CPPFLAGS="-I${PYTHON_INC}"; PYBUFFER_CPPFLAGS="-I${PYTHON_INC}"],
+                  [have_python=no])
+])
+
+AC_MSG_CHECKING([whether to build PyMUSIC])
+AS_IF([test "x$have_python" = "xyes"], [],
+      [AS_IF([test "x$with_python" = "xyes"],
+             [AC_MSG_ERROR([PyMUSIC requested, but Python not found])])])
+AC_MSG_RESULT([$have_python])
+
+AX_CHECK_COMPILE_FLAG([-fno-strict-aliasing],
+                      [PYMUSIC_CXXFLAGS="-fno-strict-aliasing"; PYBUFFER_CXXFLAGS="-fno-strict-aliasing"],
+		      [])
+
+# FIXME: this means that --without-python make will not recurse into pymusic subdir
+if test "x$have_python" = "xyes"; then
+    PYMUSIC_SUBDIR="pymusic"
+else
+    PYMUSIC_SUBDIR=""
+fi
+
+AM_CONDITIONAL([HAVE_PYTHON], [test "x$have_python" = "xyes"])
+
+# if Python is found, configure and compile PyMUSIC
+if test "x$have_python" = "xyes" ; then
+ AC_CONFIG_FILES(pymusic/Makefile)
+ AC_CONFIG_FILES(pymusic/setup.py)
+fi
+
+
+AC_SUBST([HAVE_PYTHON])
+AC_SUBST([PYMUSIC_SUBDIR])
+AC_SUBST([PYEXECDIR], ${pyexecdir})
+
+AC_SUBST([PYTHON])
+AC_SUBST([PYTHON_VERSION])
+
+AC_SUBST([PYMUSIC_CPPFLAGS])
+AC_SUBST([PYMUSIC_CXXFLAGS])
+AC_SUBST([PYBUFFER_CPPFLAGS])
+AC_SUBST([PYBUFFER_CXXFLAGS])
+
+AC_SUBST(MPI_CXXFLAGS)
+AC_SUBST(MPI_CFLAGS)
+AC_SUBST(MPI_LDFLAGS)
+AC_SUBST(MUSIC_HAVE_SIZE_T)
+AC_SUBST(MUSIC_HAVE_LONG_LONG)
+AC_SUBST(MUSIC_USE_MPI)
+AC_SUBST(MUSIC_ISENDWAITALL)
+AC_SUBST(MUSIC_ANYSOURCE)
+AC_SUBST(MPI_UTILS)
+AC_SUBST(OPTIONAL_UTILS)
+AC_SUBST(TESTDIR)
+AC_SUBST(EXAMPLESDIR)
+AC_SUBST(EXTRAS)
+AC_SUBST(PKGDATADIR)
+AC_SUBST(PKGEXTRABINDIR)
+AC_SUBST(LAUNCHSTYLE)
+
+AM_CONDITIONAL([LAUNCHSTYLE_SET], [test ! -z "$LAUNCHSTYLE"])
+#AC_SUBST([TEST_SH_LIST])
+
+AC_CONFIG_FILES([
+  Makefile
+  mpidep/Makefile
+  src/Makefile
+  src/music/music-config.hh
+  src/music/version.hh
+  rudeconfig/Makefile
+  utils/Makefile
+  examples/Makefile
+  testsuite/Makefile
+  testsuite/music_tests.sh
+  testsuite/unittests/catch/Makefile
+  testsuite/sanitytests/Makefile
+  music/Makefile
+  music/predict_rank.py
+  doc/Makefile
+  extras/Makefile
+])
+
+AC_OUTPUT
+
+if test "$ac_cv_header_GL_glut_h" = "no"; then
+   AC_MSG_NOTICE([
+NOTE: viewevents will not be built since the GL/glut.h header was not
+      found on this system.  This is no problem unless you plan to
+      view spiking activity graphically.])
+fi
+
+dnl Local Variables:
+dnl comment-start: "dnl "
+dnl comment-end: ""
+dnl comment-start-skip: "\\bdnl\\b\\s *"
+dnl End:
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..a48a5a6
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,33 @@
+music (1.0.7-1) unstable; urgency=high
+
+  * Upstream release 1.0.7 (containing urgent bugfix).
+  * Updated standards version to 3.9.0.
+  * Added missing ${misc:Depends} field for libmusic-dev.
+
+ -- Mikael Djurfeldt <mdj@debian.org>  Wed, 28 Jul 2010 04:24:40 +0200
+
+music (1.0.6-1) unstable; urgency=low
+
+  * Upstream release 1.0.6.
+
+ -- Mikael Djurfeldt <mdj@debian.org>  Sun, 25 Oct 2009 12:20:08 +0100
+
+music (1.0.5-1) unstable; urgency=low
+
+  * Upstream release 1.0.5 (Closes: #524032, #526662).
+
+ -- Mikael Djurfeldt <mdj@debian.org>  Sat, 24 Oct 2009 10:41:37 +0200
+
+music (1.0.4-1) unstable; urgency=low
+
+  * Upstream release 1.0.4.
+  * Temporarily added a build dependency on libibverbs-dev (until a
+    dependency bug in libopenmpi-dev is fixed).
+
+ -- Mikael Djurfeldt <mdj@debian.org>  Wed, 01 Apr 2009 11:14:58 +0200
+
+music (1.0.3-1) unstable; urgency=low
+
+  * Initial Release (Closes: #518538, #518541, #518542, #518543, #518544)
+
+ -- Mikael Djurfeldt <mdj@debian.org>  Fri, 13 Mar 2009 11:30:35 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..479d33f
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,60 @@
+Source: music
+Priority: extra
+Maintainer: Mikael Djurfeldt <mdj@debian.org>
+Build-Depends: debhelper (>= 7), autotools-dev, autoconf, automake, libtool, libopenmpi-dev, libibverbs-dev, freeglut3-dev, texlive-latex-base, texlive-latex-extra, asymptote, chrpath
+Standards-Version: 3.9.0
+Section: libs
+Homepage: http://software.incf.org/software/music/home
+
+Package: libmusic-dev
+Section: libdevel
+Architecture: any
+Depends: libmusic1 (= ${binary:Version}), ${misc:Depends}
+Description: Multi-Simulation Coordinator for MPI -- Development files
+ MUSIC allows spike events and continuous time series to be
+ communicated between parallel applications within the same MPI job in
+ a cluster computer.  Typical usage cases are connecting models
+ developed for different simulators and connecting a parallel
+ simulator to a post-processing tool.
+ .
+ This package contains the header files which are needed to compile
+ and link programs against libmusic.
+
+Package: libmusic1
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Multi-Simulation Coordinator for MPI -- Runtime library
+ MUSIC allows spike events and continuous time series to be
+ communicated between parallel applications within the same MPI job in
+ a cluster computer.  Typical usage cases are connecting models
+ developed for different simulators and connecting a parallel
+ simulator to a post-processing tool.
+ .
+ This package contains the MUSIC library.
+
+Package: music-bin
+Section: science
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Multi-Simulation Coordinator for MPI -- Utilities
+ MUSIC allows spike events and continuous time series to be
+ communicated between parallel applications within the same MPI job in
+ a cluster computer.  Typical usage cases are connecting models
+ developed for different simulators and connecting a parallel
+ simulator to a post-processing tool.
+ .
+ This package contains the MUSIC launch utility.
+
+Package: music-doc
+Section: doc
+Architecture: all
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Multi-Simulation Coordinator for MPI -- Manual
+ MUSIC allows spike events and continuous time series to be
+ communicated between parallel applications within the same MPI job in
+ a cluster computer.  Typical usage cases are connecting models
+ developed for different simulators and connecting a parallel
+ simulator to a post-processing tool.
+ .
+ This package contains the MUSIC manual.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..4a9d064
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,37 @@
+Author(s):
+
+    Mikael Djurfeldt <mikael@djurfeldt.com>
+    Örjan Ekeberg <orjan@nada.kth.se>
+
+Copyright:
+
+    Copyright (C) 2007-2009 INCF
+
+License:
+
+    MUSIC 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; either version 3 of the License, or
+    (at your option) any later version.
+
+    MUSIC 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 should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
+
+Files in subdirectory rudeconfig have copyright:
+
+    Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+    GNU GENERAL PUBLIC LICENSE Version 2, June 1991
+
+
+File src/music/interval_tree.hh has copyright:
+    Copyright (C) 2008, 2009 Mikael Djurfeldt
+    GNU GENERAL PUBLIC LICENSE Version 3
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..7c303a3
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,4 @@
+AUTHORS
+README
+NEWS
+BUGS
diff --git a/debian/libmusic-dev.dirs b/debian/libmusic-dev.dirs
new file mode 100644
index 0000000..6319218
--- /dev/null
+++ b/debian/libmusic-dev.dirs
@@ -0,0 +1,3 @@
+usr/lib
+usr/include
+usr/share/doc/libmusic-dev/examples
diff --git a/debian/libmusic-dev.docs b/debian/libmusic-dev.docs
new file mode 100644
index 0000000..7c303a3
--- /dev/null
+++ b/debian/libmusic-dev.docs
@@ -0,0 +1,4 @@
+AUTHORS
+README
+NEWS
+BUGS
diff --git a/debian/libmusic-dev.install b/debian/libmusic-dev.install
new file mode 100644
index 0000000..f882277
--- /dev/null
+++ b/debian/libmusic-dev.install
@@ -0,0 +1,4 @@
+usr/include/*
+usr/lib/lib*.a
+usr/lib/lib*.so
+usr/lib/*.la
diff --git a/debian/libmusic1.dirs b/debian/libmusic1.dirs
new file mode 100644
index 0000000..6845771
--- /dev/null
+++ b/debian/libmusic1.dirs
@@ -0,0 +1 @@
+usr/lib
diff --git a/debian/libmusic1.docs b/debian/libmusic1.docs
new file mode 100644
index 0000000..7c303a3
--- /dev/null
+++ b/debian/libmusic1.docs
@@ -0,0 +1,4 @@
+AUTHORS
+README
+NEWS
+BUGS
diff --git a/debian/libmusic1.install b/debian/libmusic1.install
new file mode 100644
index 0000000..d0dbfd1
--- /dev/null
+++ b/debian/libmusic1.install
@@ -0,0 +1 @@
+usr/lib/lib*.so.*
diff --git a/debian/music-bin.dirs b/debian/music-bin.dirs
new file mode 100644
index 0000000..e772481
--- /dev/null
+++ b/debian/music-bin.dirs
@@ -0,0 +1 @@
+usr/bin
diff --git a/debian/music-bin.docs b/debian/music-bin.docs
new file mode 100644
index 0000000..2ca0cf4
--- /dev/null
+++ b/debian/music-bin.docs
@@ -0,0 +1,3 @@
+AUTHORS
+README
+NEWS
diff --git a/debian/music-bin.install b/debian/music-bin.install
new file mode 100644
index 0000000..68671de
--- /dev/null
+++ b/debian/music-bin.install
@@ -0,0 +1,2 @@
+usr/bin/*
+usr/share/man/man1/*
diff --git a/debian/music-doc.dirs b/debian/music-doc.dirs
new file mode 100644
index 0000000..35149a0
--- /dev/null
+++ b/debian/music-doc.dirs
@@ -0,0 +1 @@
+usr/share/doc/music-doc
diff --git a/debian/music-doc.doc-base b/debian/music-doc.doc-base
new file mode 100644
index 0000000..9745d84
--- /dev/null
+++ b/debian/music-doc.doc-base
@@ -0,0 +1,16 @@
+Document: music-manual
+Title: MUSIC Manual
+Author: Örjan Ekeberg and Mikael Djurfeldt
+Abstract: MUSIC is an API allowing large scale neuron simulators using MPI
+ internally to exchange data during runtime.  MUSIC provides
+ mechanisms to transfer massive amounts of event information and
+ continuous values from one parallel application to another.  Special
+ care has been taken to ensure that existing simulators can be
+ adapted to MUSIC.  In particular, MUSIC handles data transfer
+ between applications that use different time steps and different
+ data allocation strategies.
+Section: Science/Biology
+
+Format: PDF
+Files: /usr/share/doc/music-doc/music-manual.pdf.gz
+
diff --git a/debian/music-doc.docs b/debian/music-doc.docs
new file mode 100644
index 0000000..8f6d688
--- /dev/null
+++ b/debian/music-doc.docs
@@ -0,0 +1,4 @@
+AUTHORS
+README
+NEWS
+doc/music-manual.pdf
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..6511153
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,116 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
+CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
+else
+CROSS= --build $(DEB_BUILD_GNU_TYPE)
+endif
+
+
+
+
+# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so
+version=`ls src/.libs/lib*.so.* | \
+ awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'`
+major=`ls src/.libs/lib*.so.* | \
+ awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'`
+
+config.status: configure
+	dh_testdir
+
+ifneq "$(wildcard /usr/share/misc/config.sub)" ""
+	cp -f /usr/share/misc/config.sub config.sub
+endif
+ifneq "$(wildcard /usr/share/misc/config.guess)" ""
+	cp -f /usr/share/misc/config.guess config.guess
+endif
+	./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
+
+
+build: build-stamp
+build-stamp:  config.status 
+	dh_testdir
+
+	$(MAKE)
+
+	touch $@
+
+clean: 
+	dh_testdir
+	dh_testroot
+	rm -f build-stamp 
+
+	[ ! -f Makefile ] || $(MAKE) distclean
+	rm -f config.sub config.guess
+
+	dh_clean 
+
+install: build
+	dh_testdir
+	dh_testroot
+	dh_prep
+	dh_installdirs
+
+	$(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+
+# Remove rpaths in libraries and binaries
+	( cd $(CURDIR)/debian/tmp/usr/lib; chrpath -d libmusic.so libmusic-c.so )
+	( cd $(CURDIR)/debian/tmp/usr/bin; chrpath -d eventcounter eventgenerator eventlogger eventselect eventsink eventsource music viewevents )
+
+# Build manual
+#	( cd $(CURDIR)/doc; make music-manual.pdf )
+
+# Fill up examples directory
+	( cd $(CURDIR)/test; cp -p README clocksource.cc contsink.cc constsource.cc eventdelay.cc contdelay.cc waveproducer.cc waveconsumer.cc messagesource.cc *.music *.data *.dat $(CURDIR)/debian/libmusic-dev/usr/share/doc/libmusic-dev/examples/ )
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+	dh_testdir
+	dh_testroot
+	dh_installchangelogs ChangeLog
+	dh_installdocs
+	dh_installexamples
+	dh_install
+#	dh_installmenu
+#	dh_installdebconf	
+#	dh_installlogrotate
+#	dh_installemacsen
+#	dh_installpam
+#	dh_installmime
+#	dh_installinit
+#	dh_installcron
+#	dh_installinfo
+	dh_installman
+	dh_link
+	dh_strip
+	dh_compress
+	dh_fixperms
+#	dh_perl
+#	dh_python
+	dh_makeshlibs
+	dh_installdeb
+	dh_shlibdeps
+	dh_gencontrol
+	dh_md5sums
+	dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install 
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000..d4cae8c
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,21 @@
+eventgenerator.1
+eventlogger.1
+eventselect.1
+eventsource.1
+eventsink.1
+viewevents.1
+
+/music-manual.aux
+/music-manual.bbl
+/music-manual.blg
+/music-manual.idx
+/music-manual.ilg
+/music-manual.ind
+/music-manual.lof
+/music-manual.log
+/music-manual.pdf
+/music-manual.stamp1
+/music-manual.toc
+/waveconsumer.cc
+/waveproducer.cc
+/wavetest.music
diff --git a/doc/ChangeLog b/doc/ChangeLog
new file mode 100644
index 0000000..619d70e
--- /dev/null
+++ b/doc/ChangeLog
@@ -0,0 +1,38 @@
+2010-07-28  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.7
+
+2009-10-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.6
+
+2009-10-24  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.5
+
+	* Makefile.am: Use hard instead of soft links for manpages (in
+	order to satisfy Debian dpkg-source); Add figures to CLEANFILES.
+
+2009-04-01  Mikael Djurfeldt  <djurfeldt@nada.kth.se>
+
+	* Release 1.0.4
+
+2009-03-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.3
+
+2009-03-12  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.2
+
+2009-03-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.1
+
+2009-03-07  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventcounter.1, eventgenerator.1, eventlogger.1, eventselect.1,
+	eventselect.1, eventsink.1, eventsource.1, viewevents.1: New
+	files.
+
+	* Makefile.am: Added rules for creation of music manual.
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..63abfb6
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,62 @@
+## Process this file with Automake to create Makefile.in
+
+dist_man1_MANS = music.1 eventcounter.1 eventgenerator.1 eventlogger.1 \
+		 eventselect.1 eventsink.1 eventsource.1 viewevents.1
+
+EXTRA_DIST = music-manual.pdf
+
+figures = figures/multisim.pdf \
+	  figures/datamapping.pdf \
+	  figures/ticklogic.pdf \
+	  figures/ticklogic2.pdf \
+	  figures/timeline.pdf \
+	  figures/remapping.pdf \
+	  figures/remapping2.pdf
+
+CLEANFILES = music-manual.aux \
+	     music-manual.bbl \
+	     music-manual.blg \
+	     music-manual.idx \
+	     music-manual.ilg \
+	     music-manual.ind \
+	     music-manual.lof \
+	     music-manual.log \
+	     music-manual.toc \
+	     music-manual.stamp1 \
+	     $(figures)
+
+linked_mans = eventgenerator.1 eventlogger.1 eventselect.1 eventsink.1 \
+	      eventsource.1 viewevents.1
+
+music-manual.pdf: music-manual.bbl music-manual.ind
+	pdflatex music-manual
+	pdflatex music-manual
+
+music-manual.bbl: music-manual.stamp1
+	bibtex music-manual
+
+music-manual.ind: music-manual.stamp1
+	makeindex music-manual
+
+music-manual.stamp1: music-manual.tex music-rfc.bib music-c-int.h wavetest.music waveproducer.cc waveconsumer.cc $(figures)
+	test -f music-manual.tex || ln -s $(srcdir)/music-manual.tex
+	test -f music-rfc.bib || ln -s $(srcdir)/music-rfc.bib
+	test -f music-c-int.h || ln -s $(srcdir)/music-c-int.h
+	pdflatex music-manual
+	touch music-manual.stamp1
+
+wavetest.music:
+	ln -s $(srcdir)/../examples/wavetest.music
+
+waveproducer.cc:
+	ln -s $(srcdir)/../examples/waveproducer.cc
+
+waveconsumer.cc:
+	ln -s $(srcdir)/../examples/waveconsumer.cc
+
+$(figures): figures/%.pdf : figures/%.asy
+	test -d figures || mkdir figures
+	asy -f pdf -o $@ $<
+
+$(linked_mans):
+	cd $(srcdir) &&	ln eventcounter.1 $@
diff --git a/doc/eventcounter.1 b/doc/eventcounter.1
new file mode 100644
index 0000000..7bc5375
--- /dev/null
+++ b/doc/eventcounter.1
@@ -0,0 +1,134 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH EVENTCOUNTER 1 "March  5, 2009"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+eventcounter, eventgenerator, eventlogger, eventselect, eventsink,
+eventsource, viewevents \- utility applications which can be used
+together with other MUSIC-aware applications in multi-simulations
+.SH SYNOPSIS
+.B eventcounter
+.RB [ "\-tbmh " ]
+.I "n_units prefix "
+[
+.I suffix
+]
+.br
+.B eventgenerator
+.RB [ "\-tbfmih " ]
+.I "n_units"
+.br
+.B eventlogger
+.RB [ "\-tlbmih " ]
+.br
+.B eventselect
+.RB [ "\-th " ]
+.I n_units units
+.br
+.B eventsink
+.RB [ "\-tmih " ]
+.I "n_units prefix "
+[
+.I suffix
+]
+.br
+.B eventsource
+.RB [ "\-tbmih " ]
+.I "n_units prefix "
+[
+.I suffix
+]
+.br
+.B viewevents
+.RB [ "\-tshT " ]
+.I "configfile"
+.SH DESCRIPTION
+This manual page documents briefly a set of MUSIC-aware utility
+applications provided together with MUSIC library.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBeventcounter\fP receives spikes through a MUSIC input port, counts
+all spikes for each index and writes the frequencies to a set of files
+with names
+.I "prefix rank suffix"
+.PP
+\fBeventgenerator\fP generates spikes from a Poisson distribution.
+.PP
+\fBeventlogger\fP logs spikes from a MUSIC port.
+.PP
+\fBeventselect\fP receives events from an input port of width
+.I "n_units "
+and sends events for the subset of id:s specified in the file
+.I "units"
+.PP
+\fBeventsink\fP receives spikes through a MUSIC input port and
+writes these to a set of files with names
+.I "prefix rank suffix"
+.PP
+\fBeventsource\fP reads spikes from a set of files with names
+.I "prefix rank suffix"
+and propagates these spikes through a MUSIC output port.
+.PP
+\fBviewevents\fP reads spikes from a MUSIC input port and displays
+them as a 3D graphical representation.
+.SH OPTIONS
+The utilities follow the usual GNU command line syntax, with long
+options starting with two dashes (`-').
+A summary of options is included below.
+.TP
+.B \-b ticks, \-\-maxbuffered ticks
+Specify maximal amount of data buffered.
+.TP
+.B \-f freq, \-\-frequency
+Specify average frequency (default 10 Hz).
+.TP
+.B \-h, \-\-help
+Show usage information.
+.TP
+.B \-i, \-\-indextype
+Select global (default) or local indices. (Used for testing and
+benchmarking purposes.)
+.TP
+.B \-l latency, \-\-acclatency latency
+Specify acceptable data latency (s).
+.TP
+.B \-m type, \-\-imaptype type
+Select linear (default) or roundrobin index map.
+.TP
+.B \-s scaling, \-\-scaletime scaling
+Specify real time to simulated time scale factor (s).  If omitted, the
+visualization runs at full speed.
+.TP
+.B \-t timestep, \-\-timestep timestep
+Specify time between tick() calls (default 0.01 s).
+.TP
+.B \-T title, \-\-title title
+Specify window title.
+.SH SEE ALSO
+.BR music (1)
+.\" .BR baz (1).
+.\" .br
+.\" The programs are documented fully by
+.\" .IR "The Rise and Fall of a Fooish Bar" ,
+.\" available via the Info system.
+.SH AUTHOR
+MUSIC was written by Mikael Djurfeldt and Örjan Ekeberg for INCF.
+viewevents was written by Johannes Hjorth for INCF.
+.PP
+This manual page was written by Mikael Djurfeldt <mdj@debian.org>,
+for the Debian project (but may be used by others).
diff --git a/doc/figures/.gitignore b/doc/figures/.gitignore
new file mode 100644
index 0000000..23bd3a6
--- /dev/null
+++ b/doc/figures/.gitignore
@@ -0,0 +1,7 @@
+/datamapping.pdf
+/multisim.pdf
+/remapping.pdf
+/remapping2.pdf
+/ticklogic.pdf
+/ticklogic2.pdf
+/timeline.pdf
diff --git a/doc/figures/dataconvergence.asy b/doc/figures/dataconvergence.asy
new file mode 100644
index 0000000..22d7548
--- /dev/null
+++ b/doc/figures/dataconvergence.asy
@@ -0,0 +1,21 @@
+unitsize(10mm);
+
+pair p1=(1,2);
+pair p2=(6,2.1);
+
+void application(int n, pair pos) {
+  for (int i=n-1; i>=0; --i) {
+    filldraw(box(pos-(1,1)+i*(0.1, 0.1), pos+(1,1)+i*(0.1, 0.1)),
+	     lightgray, black);
+  }
+}
+
+application(5, p1);
+
+draw("2.6\,Tb/s", p1+(1.2,0.2){right}..{right}p2+(-0.9,0.1), black+1, Arrow);
+draw("2.6\,Gb/s", p2+(1.2,0.1){right}..{right}p2+(3.2,0.1), black+1, Arrow);
+
+application(3, p2);
+
+label("Simulator", p1);
+label("EEG", p2);
diff --git a/doc/figures/datamapping.asy b/doc/figures/datamapping.asy
new file mode 100644
index 0000000..f1f2bf0
--- /dev/null
+++ b/doc/figures/datamapping.asy
@@ -0,0 +1,56 @@
+unitsize(10mm);
+
+label(scale(1.5)*"Sender", (1.5, 10.5));
+label(scale(1.5)*"Receiver", (11.5, 10.5));
+
+fill(box((2,0), (3,10)), gray(0.8));
+draw(box((0,0), (3,10)));
+
+fill(box((10,0), (11,10)), gray(0.8));
+draw(box((10,0), (13,10)));
+
+// Sender arrows
+for (real y=0.75; y<9.6; y+=0.5)
+  draw((1.0,y)--(2.0,y), gray(0.5), Arrow);
+
+// Sender data array
+filldraw(box((0.5,0.5),(1.0,9.5)), gray(0.9), black);
+for (real y=0.5; y<9.6; y+=0.5)
+  draw((0.5,y)--(1.0,y));
+
+label(rotate(90)*"Distributed sender data", (0.26, 5.0));
+
+// Receiver arrows
+for (real y=0.75; y<9.6; y+=0.5)
+  draw((11.0,y)--(12.0,y), gray(0.5), Arrow);
+
+// Receiver data array
+filldraw(box((12.0,0.5),(12.5,9.5)), gray(0.9), black);
+for (real y=0.5; y<9.6; y+=0.5)
+  draw((12.0,y)--(12.5,y));
+
+label(rotate(-90)*"Distributed receiver data", (12.74, 5.0));
+
+draw((-0.2,2.5)--(3.2,2.5), dashed);
+draw((-0.2,5.0)--(3.2,5.0), dashed);
+draw((-0.2,7.5)--(3.2,7.5), dashed);
+
+draw((9.8,3.5)--(13.2,3.5), dashed);
+draw((9.8,6.5)--(13.2,6.5), dashed);
+
+// Fan-in
+draw((3,0.5){right}..tension 1.5 ..{right}(5.5,5.0));
+draw((3,2.5){right}..{right}(5.5,5.0));
+draw((3,5.0){right}..{right}(5.5,5.0));
+draw((3,7.5){right}..{right}(5.5,5.0));
+draw((3,9.5){right}..tension 1.5 ..{right}(5.5,5.0));
+
+// Fan-out
+draw((7.5,5.0){right}..tension 1.5 ..{right}(10,0.5));
+draw((7.5,5.0){right}..{right}(10,3.5));
+draw((7.5,5.0){right}..{right}(10,6.5));
+draw((7.5,5.0){right}..tension 1.5 ..{right}(10,9.5));
+
+draw((5.4,5.0)--(7.6,5.0), black+1, Arrow(position=0.8));
+draw((5.5, 4.5)--(6.0,5.5));
+label("Width", (6.0, 6.0));
diff --git a/doc/figures/messysim.asy b/doc/figures/messysim.asy
new file mode 100644
index 0000000..a505c21
--- /dev/null
+++ b/doc/figures/messysim.asy
@@ -0,0 +1,103 @@
+unitsize(10mm);
+
+pair p11=(2,3);
+pair p12=(1.5,2.5);
+pair p13=(1,2);
+
+pair p21=(6,2);
+pair p22=(6.5,1.5);
+pair p23=(7,1);
+
+pair p31=(5,5);
+pair p32=(5.3,5.1);
+pair p33=(5.6,5.2);
+pair p34=(5.9,5.3);
+pair p35=(6.2,5.4);
+
+void application(pair pos) {
+  filldraw(box(pos-(1,1), pos+(1,1)), lightgray, black);
+}
+
+void flow(pair a, pair adir, int aoffs,
+	  pair b, pair bdir, int boffs) {
+  pair ao = (adir.y, -adir.x)*0.1*aoffs;
+  pair bo = (-bdir.y, bdir.x)*0.1*boffs;
+  draw(a+adir+ao{adir}..{-bdir}b+bdir+bo, black, Arrow);
+}
+
+
+application(p11);
+application(p12);
+application(p13);
+
+application(p21);
+application(p22);
+application(p23);
+
+application(p31);
+application(p32);
+application(p33);
+application(p34);
+application(p35);
+
+flow(p11, E, -2, p21, W, -2);
+flow(p11, E, 0, p22, W, -2);
+flow(p11, E, 2, p23, W, -2);
+flow(p12, E, -2, p21, W, 0);
+flow(p12, E, 0, p22, W, 0);
+flow(p12, E, 2, p23, W, 0);
+flow(p13, E, -2, p21, W, 2);
+flow(p13, E, 0, p22, W, 2);
+flow(p13, E, 2, p23, W, 2);
+
+flow(p11, N, -4, p31, W, -2);
+flow(p11, N, -2, p32, W, -2);
+flow(p11, N, 0, p33, W, -2);
+flow(p11, N, 2, p34, W, -2);
+flow(p11, N, 4, p35, W, -2);
+flow(p12, N, -4, p31, W, 0);
+flow(p12, N, -2, p32, W, 0);
+flow(p12, N, 0, p33, W, 0);
+flow(p12, N, 2, p34, W, 0);
+flow(p12, N, 4, p35, W, 0);
+flow(p13, N, -4, p31, W, 2);
+flow(p13, N, -2, p32, W, 2);
+flow(p13, N, 0, p33, W, 2);
+flow(p13, N, 2, p34, W, 2);
+flow(p13, N, 4, p35, W, 2);
+
+flow(p21, N, 3, p31, S, 2);
+flow(p21, N, 4, p32, S, 2);
+flow(p21, N, 5, p33, S, 2);
+flow(p21, N, 6, p34, S, 2);
+flow(p21, N, 7, p35, S, 2);
+flow(p22, N, 3, p31, S, 4);
+flow(p22, N, 4, p32, S, 4);
+flow(p22, N, 5, p33, S, 4);
+flow(p22, N, 6, p34, S, 4);
+flow(p22, N, 7, p35, S, 4);
+flow(p23, N, 3, p31, S, 6);
+flow(p23, N, 4, p32, S, 6);
+flow(p23, N, 5, p33, S, 6);
+flow(p23, N, 6, p34, S, 6);
+flow(p23, N, 7, p35, S, 6);
+
+flow(p31, S, 2, p21, N, 8);
+flow(p31, S, 4, p22, N, 8);
+flow(p31, S, 6, p23, N, 8);
+flow(p32, S, 2, p21, N, 6);
+flow(p32, S, 4, p22, N, 6);
+flow(p32, S, 6, p23, N, 6);
+flow(p33, S, 2, p21, N, 4);
+flow(p33, S, 4, p22, N, 4);
+flow(p33, S, 6, p23, N, 4);
+flow(p34, S, 2, p21, N, 2);
+flow(p34, S, 4, p22, N, 2);
+flow(p34, S, 6, p23, N, 2);
+flow(p35, S, 2, p21, N, 0);
+flow(p35, S, 4, p22, N, 0);
+flow(p35, S, 6, p23, N, 0);
+
+label("LGN", p13);
+label("NEST", p23);
+label("Neuron", p35);
diff --git a/doc/figures/multisim.asy b/doc/figures/multisim.asy
new file mode 100644
index 0000000..44796e5
--- /dev/null
+++ b/doc/figures/multisim.asy
@@ -0,0 +1,30 @@
+unitsize(10mm);
+
+pair p1=(1,2);
+pair p2=(6,1);
+pair p3=(5,5);
+
+void application(int n, pair pos) {
+  for (int i=n-1; i>=0; --i) {
+    filldraw(box(pos-(1,1)+i*(0.1, 0.1), pos+(1,1)+i*(0.1, 0.1)),
+	     lightgray, black);
+  }
+}
+
+application(5, p1);
+
+draw(p1+(0.2,1.2){up}..{right}p3+(-0.9,0.1), black+1, Arrow);
+draw(p1+(1.2,0.2){right}..{right}p2+(-0.9,0.1), black+1, Arrow);
+
+application(3, p2);
+
+pair d=(0.3,0);
+
+draw(p3+(0.1,-0.9)-d{down}..{down}p2+(0.1,1.1)-d, black+1, Arrow);
+draw(p2+(0.1,1.1)+d{up}..{up}p3+(0.1,-0.9)+d, black+1, Arrow);
+
+application(3, p3);
+
+label("Appl. $A$", p1);
+label("Appl. $B$", p2);
+label("Appl. $C$", p3);
diff --git a/doc/figures/receiverport.asy b/doc/figures/receiverport.asy
new file mode 100644
index 0000000..ac176bc
--- /dev/null
+++ b/doc/figures/receiverport.asy
@@ -0,0 +1,22 @@
+unitsize(10mm);
+
+fill(box((10,0), (11,10)), gray(0.8));
+draw(box((10,0), (13,10)));
+
+// Receiver arrows
+for (real y=0.75; y<9.6; y+=0.5)
+  draw((11.0,y)--(12.0,y), gray(0.5), Arrow);
+
+// Receiver data array
+filldraw(box((12.0,0.5),(12.5,9.5)), gray(0.9), black);
+for (real y=0.5; y<9.6; y+=0.5)
+  draw((12.0,y)--(12.5,y));
+
+label(rotate(-90)*"Distributed receiver data", (12.74, 5.0));
+
+draw((9.8,3.5)--(13.2,3.5), dashed);
+draw((9.8,6.5)--(13.2,6.5), dashed);
+
+// Port
+filldraw(box((9.5,0.5),(10.0,9.5)), white, black);
+label(rotate(-90)*"Input Port", (9.74, 5.0));
diff --git a/doc/figures/remapping.asy b/doc/figures/remapping.asy
new file mode 100644
index 0000000..ae69789
--- /dev/null
+++ b/doc/figures/remapping.asy
@@ -0,0 +1,46 @@
+unitsize(10mm);
+
+real[] prm = {5, 8, 0, 2, 9, 7, 4, 3, 6, 12, 13, 11, 15, 1, 10, 17, 14, 16};
+
+label(scale(1.5)*"Sender", (1.5, 10.5));
+label(scale(1.5)*"Receiver", (7.5, 10.5));
+
+filldraw(box((0,0), (3,10)), gray(0.9), black);
+
+filldraw(box((5,0), (10,10)), gray(0.9), black);
+
+// Sender arrows
+for (real y=0.75; y<9.6; y+=0.5) {
+  draw((1.0,y)--(2.0,y), gray(0.5), Arrow);
+  draw((2.5,y)--(5.5,y), gray(0.5), Arrow);
+
+  // Sender neurons
+  filldraw(circle((1.0,y), 0.2), gray(0.5), black);
+
+  // Reveiver neurons
+  filldraw(circle((9.0,y), 0.2), gray(0.5), black);
+}
+
+// Sender data array
+filldraw(box((2.0,0.5),(2.5,9.5)), gray(0.7), black);
+for (real y=0.5; y<9.6; y+=0.5) {
+  draw((2.0,y)--(2.5,y));
+}
+
+// Receiver data array
+filldraw(box((5.5,0.5),(6,9.5)), gray(0.7), black);
+for (real y=0.5; y<9.6; y+=0.5) {
+  draw((5.5,y)--(6,y));
+}
+
+// Remapping arrows
+for (int i=0; i<18; ++i)
+  draw((6,0.75+i*0.5){right}..{right}(8.8,0.75+prm[i]*0.5), Arrow);
+
+// Indicate processor borders
+draw((-0.2,2.5)--(3.2,2.5), dashed);
+draw((-0.2,5.0)--(3.2,5.0), dashed);
+draw((-0.2,7.5)--(3.2,7.5), dashed);
+
+draw((4.8,3.5)--(10.2,3.5), dashed);
+draw((4.8,6.5)--(10.2,6.5), dashed);
diff --git a/doc/figures/remapping2.asy b/doc/figures/remapping2.asy
new file mode 100644
index 0000000..5e304de
--- /dev/null
+++ b/doc/figures/remapping2.asy
@@ -0,0 +1,46 @@
+unitsize(10mm);
+
+real[] prm = {5, 8, 0, 2, 9, 7, 4, 3, 6, 12, 13, 11, 15, 1, 10, 17, 14, 16};
+
+label(scale(1.5)*"Sender", (1.5, 10.5));
+label(scale(1.5)*"Receiver", (7.5, 10.5));
+
+filldraw(box((0,0), (3,10)), gray(0.9), black);
+
+filldraw(box((5,0), (10,10)), gray(0.9), black);
+
+// Sender arrows
+for (real y=0.75; y<9.6; y+=0.5) {
+  draw((1.0,y)--(2.0,y), gray(0.5), Arrow);
+  draw((5.5,y)--(8.8,y), gray(0.5), Arrow);
+
+  // Sender neurons
+  filldraw(circle((1.0,y), 0.2), gray(0.5), black);
+
+  // Reveiver neurons
+  filldraw(circle((9.0,y), 0.2), gray(0.5), black);
+}
+
+// Sender data array
+filldraw(box((2.0,0.5),(2.5,9.5)), gray(0.7), black);
+for (real y=0.5; y<9.6; y+=0.5) {
+  draw((2.0,y)--(2.5,y));
+}
+
+// Receiver data array
+filldraw(box((5.5,0.5),(6,9.5)), gray(0.7), black);
+for (real y=0.5; y<9.6; y+=0.5) {
+  draw((5.5,y)--(6,y));
+}
+
+// Remapping arrows
+for (int i=0; i<18; ++i)
+  draw((2.5,0.75+i*0.5){right}..{right}(5.5,0.75+prm[i]*0.5), Arrow);
+
+// Indicate processor borders
+draw((-0.2,2.5)--(3.2,2.5), dashed);
+draw((-0.2,5.0)--(3.2,5.0), dashed);
+draw((-0.2,7.5)--(3.2,7.5), dashed);
+
+draw((4.8,3.5)--(10.2,3.5), dashed);
+draw((4.8,6.5)--(10.2,6.5), dashed);
diff --git a/doc/figures/senderport.asy b/doc/figures/senderport.asy
new file mode 100644
index 0000000..7f4a57f
--- /dev/null
+++ b/doc/figures/senderport.asy
@@ -0,0 +1,23 @@
+unitsize(10mm);
+
+fill(box((2,0), (3,10)), gray(0.8));
+draw(box((0,0), (3,10)));
+
+// Sender arrows
+for (real y=0.75; y<9.6; y+=0.5)
+  draw((1.0,y)--(2.0,y), gray(0.5), Arrow);
+
+// Sender data array
+filldraw(box((0.5,0.5),(1.0,9.5)), gray(0.9), black);
+for (real y=0.5; y<9.6; y+=0.5)
+  draw((0.5,y)--(1.0,y));
+
+label(rotate(90)*"Distributed sender data", (0.26, 5.0));
+
+draw((-0.2,2.5)--(3.2,2.5), dashed);
+draw((-0.2,5.0)--(3.2,5.0), dashed);
+draw((-0.2,7.5)--(3.2,7.5), dashed);
+
+// Port
+filldraw(box((3.0,0.5),(3.5,9.5)), white, black);
+label(rotate(90)*"Output Port", (3.24, 5.0));
diff --git a/doc/figures/ticklogic.asy b/doc/figures/ticklogic.asy
new file mode 100644
index 0000000..51ffc7c
--- /dev/null
+++ b/doc/figures/ticklogic.asy
@@ -0,0 +1,39 @@
+import markers;
+
+unitsize(10mm);
+
+label("Sender", (5, 8.5));
+label("MUSIC", (0, 3), NE);
+label("MPI", (0, 4.5), NE);
+label("Receiver", (5, 1.5));
+
+draw(box((10,8), (0,9)), dashed);
+filldraw(box((10,3), (0,7)), gray(0.8), dotted);
+draw(box((10,1), (0,2)), dashed);
+filldraw(box((10,5.5), (0,4.5)), gray(0.5));
+
+draw("Simulated Time", (0,0)--(10,0), Arrow);
+
+// Senders ticks
+int i=1;
+for (real t=1; t<10; t+=2, ++i)
+  draw(format("$s_{%d}$", i), (t, 8)--(t, 7), Arrow);
+
+// Receivers ticks
+int i=1;
+for (real t=2.5; t<10; t+=5, ++i)
+  draw(format("$r_{%d}$", i), (t, 3)--(t, 2), Arrow);
+
+void transfer(real s1, real s2, real r1, real ts) {
+  draw((s1,6.8)--(s2,6.8), marker(scale(2)*dotframe));
+  draw((r1,6.8){down}..{down}(s2,5.5), Arrow);
+  draw((s2,5.5){down}..{down}(s2-ts,4.5), blue, Arrow);
+  draw((s2-ts,4.5){down}..{down}(r1,3.2), Arrow);
+  draw((r1,3.1), marker(scale(2)*dotframe));
+}
+
+// First transfer
+transfer(1, 3, 2.5, 1.5);
+
+// Second transfer
+transfer(7, 9, 7.5, 1.5);
diff --git a/doc/figures/ticklogic2.asy b/doc/figures/ticklogic2.asy
new file mode 100644
index 0000000..9fdefff
--- /dev/null
+++ b/doc/figures/ticklogic2.asy
@@ -0,0 +1,38 @@
+import markers;
+
+unitsize(10mm);
+
+label("Sender", (5, 8.5));
+label("MUSIC", (0, 3), NE);
+label("MPI", (0, 4.5), NE);
+label("Receiver", (5, 1.5));
+
+draw(box((10,8), (0,9)), dashed);
+filldraw(box((10,3), (0,7)), gray(0.8), dotted);
+draw(box((10,1), (0,2)), dashed);
+filldraw(box((10,5.5), (0,4.5)), gray(0.5));
+
+draw("Simulated Time", (0,0)--(10,0), Arrow);
+
+// Senders ticks
+int i=1;
+for (real t=2.5; t<10; t+=5, ++i)
+  draw(format("$s_{%d}$", i), (t, 8)--(t, 7), Arrow);
+
+// Receivers ticks
+int i=1;
+for (real t=1; t<10; t+=2, ++i)
+  draw(format("$r_{%d}$", i), (t, 3)--(t, 2), Arrow);
+
+void transfer(real s1, real s2, real r1, real ts) {
+  draw((s1,6.8)--(s2,6.8), marker(scale(2)*dotframe));
+  draw((r1,6.8){down}..{down}(s2,5.5), Arrow);
+  draw((s2,5.5){down}..{down}(s2-ts,4.5), blue, Arrow);
+  draw((s2-ts,4.5){down}..{down}(r1,3.2), Arrow);
+  draw((r1,3.1), marker(scale(2)*dotframe));
+}
+
+// Transfers
+transfer(2.5, 7.5, 3, 4.5);
+transfer(2.5, 7.5, 5, 4.5);
+transfer(2.5, 7.5, 7, 4.5);
diff --git a/doc/figures/timeline.asy b/doc/figures/timeline.asy
new file mode 100644
index 0000000..5cbcf6c
--- /dev/null
+++ b/doc/figures/timeline.asy
@@ -0,0 +1,41 @@
+import markers;
+
+unitsize(10mm);
+
+real Apos = 6;
+real Bpos = 2;
+
+real Alag = 1.5;
+real Blag = 0.0;
+
+real Aticks[] ={3, 5, 7, 9, 11, 13};
+real Bticks[] ={3, 7, 11};
+
+label(scale(2)*"A", (0, Apos), W);
+label(scale(2)*"B", (0, Bpos), W);
+
+// Application A ticks
+for (int i=0; i<Aticks.length; ++i)
+  fill(box((Aticks[i]-0.2, Apos-1), (Aticks[i]+0.2, Apos+1)), gray(0.8));
+
+// Application B ticks
+for (int i=0; i<Bticks.length; ++i)
+  fill(box((Bticks[i]-0.2, Bpos-1), (Bticks[i]+0.2, Bpos+1)), gray(0.8));
+
+void transfer(int a, int b) {
+  draw("delay", (Bticks[b],Bpos+0.8)--(Bticks[b]-2.5,Bpos+0.8),
+       S, marker(scale(2)*dotframe));
+  draw((Aticks[a],Apos-1){down}..{down}(Bticks[b],Bpos+1), Arrow);
+  draw((Bticks[b]-2.5+1.5,Apos-1){down}..{down}(Bticks[b]-2.5,Bpos+0.8),
+     blue+dashed, Arrow);
+}
+
+transfer(0, 0);
+transfer(2, 1);
+transfer(4, 2);
+
+
+draw(box((Alag,Apos-1), (Alag+13,Apos+1)));
+draw(box((Blag,Bpos-1), (Blag+13,Bpos+1)));
+
+draw("Wallclock Time", (0,0)--(15,0), Arrow);
diff --git a/doc/music-c-int.h b/doc/music-c-int.h
new file mode 100644
index 0000000..102ccfc
--- /dev/null
+++ b/doc/music-c-int.h
@@ -0,0 +1,132 @@
+/* Setup */
+
+MUSIC_Setup *MUSIC_createSetup (int *argc, char ***argv);
+
+/* Communicators */
+
+MPI_Intracomm MUSIC_Setup_communicator (MUSIC_setup *setup);
+
+/* Port creation */
+
+MUSIC_ContOutputPort *MUSIC_publishContOutput (MUSIC_setup *setup,
+					       char *id);
+MUSIC_ContInputPort *MUSIC_publishContInput (MUSIC_setup *setup,
+					     char *id);
+MUSIC_EventOutputPort *MUSIC_publishEventOutput (MUSIC_setup *setup,
+						 char *id);
+MUSIC_EventInputPort *MUSIC_publishEventInput (MUSIC_setup *setup,
+					       char *id);
+MUSIC_MessageOutputPort *MUSIC_publishMessageOutput (MUSIC_setup *setup,
+						     char *id);
+MUSIC_MessageInputPort *MUSIC_publishMessageInput (MUSIC_setup *setup,
+						   char *id);
+
+void MUSIC_destroyContOutput (MUSIC_ContOutputPort* port);
+void MUSIC_destroyContInput (MUSIC_ContInputPort* port);
+void MUSIC_destroyEventOutput (MUSIC_EventOutputPort* port);
+void MUSIC_destroyEventInput (MUSIC_EventInputPort* port);
+void MUSIC_destroyMessageOutput (MUSIC_MessageOutputPort* port);
+void MUSIC_destroyMessageInput (MUSIC_MessageInputPort* port);
+
+/* General port methods */
+
+/* Xxx = Cont | Event
+   Ddd = Output | Input */
+
+int MUSIC_XxxDddPort_isConnected (XxxDddPort *port);
+int MUSIC_MessageDddPort_isConnected (MessageDddPort *port);
+int MUSIC_XxxDddPort_hasWidth (XxxDddPort *port);
+int MUSIC_XxxDddPort_width (XxxDddPort *port);
+
+/* Mapping */
+
+/* No arguments are optional. */
+
+void MUSIC_ContOutputPort_map (MUSIC_ContOutputPort *port,
+			       MUSIC_ContData *dMap,
+			       int maxBuffered);
+
+void MUSIC_ContInputPort_map (MUSIC_ContInputPort *port,
+			      MUSIC_ContData *dMap,
+			      double delay,
+			      int maxBuffered,
+			      int interpolate);
+
+void MUSIC_EventOutputPort_map (MUSIC_EventOutputPort *port,
+				MUSIC_IndexMap *indices,
+				int maxBuffered);
+
+typedef void MUSIC_EventHandler (double t, int id);
+
+void MUSIC_EventInputPort_map (MUSIC_EventInputPort *port,
+			       MUSIC_IndexMap *indices,
+			       MUSIC_EventHandler *handleEvent,
+			       double accLatency,
+			       int maxBuffered);
+
+void MUSIC_MessageOutputPort_map (MUSIC_MessageOutputPort *port,
+				  int maxBuffered);
+
+typedef void MUSIC_MessageHandler (double t, void *msg, size_t size);
+
+void MUSIC_MessageInputPort_map (MUSIC_MessageInputPort *port,
+				 MUSIC_MessageHandler *handleMessage,
+				 double accLatency,
+				 int maxBuffered);
+
+/* Index maps */
+
+MUSIC_PermutationIndex *MUSIC_createPermutationIndex (int *indices,
+						      int size);
+
+void MUSIC_destroyPermutationIndex (MUSIC_PermutationIndex *index);
+
+MUSIC_LinearIndex *MUSIC_createLinearIndex (int baseIndex,
+					    int size);
+
+void MUSIC_destroyLinearIndex (MUSIC_LinearIndex *index);
+
+/* Data maps */
+
+/* Exception: The map argument can take any type of index map. */
+
+MUSIC_ArrayData *MUSIC_createArrayData (void *buffer,
+					MPI_Datatype type,
+					void *map);
+
+/* Exception: MUSIC_createLinearArrayData corresponds to
+   c++ music::ArrayData::ArrayData (..., ..., ..., ...) */
+
+MUSIC_ArrayData *MUSIC_createLinearArrayData (void *buffer,
+					      MPI_Datatype type,
+					      int baseIndex,
+					      int size);
+
+void MUSIC_destroyArrayData (MUSIC_ArrayData *arrayData);
+
+/* Configuration variables */
+
+/* Exceptions: Result is char *
+   Extra maxlen argument prevents buffer overflow.
+   Result is terminated by \0 unless longer than maxlen - 1 */
+
+int MUSIC_config (MUSIC_Setup *setup,
+		  char *name,
+		  char *result,
+		  size_t maxLen);
+
+int MUSIC_config (MUSIC_Setup *setup, char *name, int *result);
+
+int MUSIC_config (MUSIC_Setup *setup, char *name, double *result);
+
+/* Runtime */
+
+MUSIC_Runtime *MUSIC_createRuntime (MUSIC_Setup *setup, double h);
+
+void MUSIC_tick (MUSIC_Runtime *runtime);
+
+double MUSIC_time (MUSIC_Runtime *runtime);
+
+/* Finalization */
+
+void MUSIC_destroyRuntime (MUSIC_Runtime *runtime);
diff --git a/doc/music-manual.tex b/doc/music-manual.tex
new file mode 100644
index 0000000..d4205e7
--- /dev/null
+++ b/doc/music-manual.tex
@@ -0,0 +1,1748 @@
+\documentclass[a4paper,twoside]{report}
+
+\usepackage[numbers]{natbib}
+\citestyle{newapa}
+\usepackage[utf8]{inputenc}
+\usepackage{fancyhdr}
+\usepackage{color}
+\usepackage{graphicx}
+\usepackage{listings}
+\usepackage{makeidx}
+\usepackage{comment}
+
+%%%%% Formatting %%%%%
+
+% Use the metatext environment around text that should not appear in
+% the final document
+%\newenvironment{metatext}%
+%{\color{blue}}%
+%{}
+\excludecomment{metatext}
+
+% Use the rationale environment around arguments for design decisions
+\newenvironment{rationale}%
+{\par\begin{quote}\textbf{Rationale:}}%
+{\par\end{quote}}
+
+
+% Use the head environment around method heads
+\lstnewenvironment{head}[1]%
+{\lstset{frame=topline,emph={#1},emphstyle=\color{blue}\textbf}}%
+{}
+
+
+% Use the parameters environment after heads
+\newenvironment{parameters}%
+{\begin{tabular}{@{\hspace{2em}}lp{0.6\textwidth}}}%
+{\end{tabular}\par\vspace{1mm}\par\hrule\par\vspace{5mm}}
+
+
+% Use the code environment around method code examples
+\lstnewenvironment{code}[1]%
+{\lstset{frame=single,caption={#1}}}%
+{}
+
+\renewcommand{\lstlistingname}{Example}
+
+% Use the responsible command to indicate which author is responsible
+% for the present section
+\newcommand{\responsible}[1]%
+{{\color{red}[#1 is responsible for this section]}}
+
+
+\fancyhead{}
+\fancyhead[L]{\slshape\leftmark}
+
+\pagestyle{fancy}
+\makeindex
+
+%%%%% Actual content starts here %%%%%
+\begin{document}
+
+\lstset{language=C++,identifierstyle=\ttfamily}
+
+\title{MUSIC --- Multi-Simulation Coordinator\\[2ex]
+  Users Manual\\}
+
+\author{Örjan Ekeberg and Mikael Djurfeldt}
+
+\maketitle
+
+\begin{abstract}
+  MUSIC is an API allowing large scale neuron simulators using MPI
+  internally to exchange data during runtime.  MUSIC provides
+  mechanisms to transfer massive amounts of event information and
+  continuous values from one parallel application to another.  Special
+  care has been taken to ensure that existing simulators can be
+  adapted to MUSIC.  In particular, MUSIC handles data transfer
+  between applications that use different time steps and different
+  data allocation strategies.
+\end{abstract}
+
+
+\tableofcontents
+
+\listoffigures
+
+\chapter{Introduction}
+
+This document constitutes the final specification for the
+multi-simulation coordinator MUSIC.
+
+\section{Scope}
+
+MUSIC is a standard for run-time exchange of data between parallel
+applications in a cluster environment.  The standard is designed
+specifically for interconnecting large scale neuronal network
+simulators, either with each-other or with other tools.
+
+A typical usage example is illustrated in figure~\ref{fig:multisim},
+where three applications ($A$, $B$, and $C$) are executing in parallel
+while exchanging data via MUSIC.  We will refer to this as a
+\emph{multi-simulation}, since the participating applications
+typically are neuronal simulators, or tools to support such
+simulators.  In this example, application $A$ produces runtime data
+which is then used by $B$ and $C$.  In addition, $B$ and $C$ mutually
+send data to each other.  The data sent between applications can be
+either event based, such as neuronal spikes, or graded continuous
+values, for example membrane voltages.
+
+\begin{figure}
+  \begin{center}
+    \includegraphics[width=0.5\textwidth]{figures/multisim}
+    \caption[Typical multi-simulation]{\label{fig:multisim}
+      Illustration of a typical multi-simulation using MUSIC.  Three
+      applications, $A$, $B$, and $C$, are exchanging data during
+      runtime.
+    }
+  \end{center}
+\end{figure}
+
+The primary objective of MUSIC is to support multi-simulations where
+each participating application itself is a parallel simulator with the
+capacity to produce and/or consume massive amounts of data.  This
+promotes \emph{inter-operability} by allowing models written for
+different simulators to be simulated together in a larger system.  It
+also enables \emph{re-usability} of models or tools by providing a
+standard interface.  The fact that data is spread out over a number of
+processors makes it non-trivial to coordinate the transfer of data so
+that it reaches the right destination at the right time.  The task for
+MUSIC is to relieve the applications from handling this complexity.
+
+
+\section{Design Goals}
+
+\subsection{Portability}
+
+The MUSIC library and utilities have been designed to run
+smoothly on state-of-the-art high-performance hardware.  For maximal
+portability, the software is written in C++, which is the de facto
+standard for current high-end hardware.  MUSIC also provides a
+C-interface, making it possible for applications written in C or
+FORTRAN to participate in a MUSIC multi-simulation.
+
+Most, if not all, current efforts in large scale neuronal simulations
+are based on the MPI\index{MPI} standard.  MUSIC is built on top of
+MPI, and uses it to run the different simulators.  MUSIC provides
+means to allow each simulator to use MPI internally without
+interfering with the others.
+
+MUSIC has been developed using two reference platforms: Intel-based
+multi-core workstations and the IBM
+BlueGene/L\index{BlueGene/L}\index{IBM BlueGene} supercomputer.  These
+platforms can be considered as two extremes, where the multi-core
+machine represents a small parallel environment while the BlueGene/L
+represents a large scale massively parallel supercomputer with special
+requirements.  In particular, the compute nodes on the BlueGene/L do
+not support multiple threads or processes.
+
+
+\subsection{Simplicity}
+\label{sec:simplicity}
+
+For MUSIC to be useful, it must be possible to adapt existing
+simulators so that they can participate in a multi-simulation without
+too much effort.  We rely on the simulator developers to make these
+adaptations.  An important design goal has therefore been to adapt the
+design to the typical structure of current simulators.  It should be
+possible to add MUSIC library support without invasive restructuring
+of the existing code.
+
+The primary requirements on an application using MUSIC is that it
+declares what data should be exported and imported and that it
+repeatedly calls a function at regular intervals during the simulation
+to allow MUSIC to make the actual data transfer.
+
+
+\subsection{Independence}
+
+The MUSIC interface ensures that each individual application does not
+need special adaptation to specific properties of other applications.
+The application only needs to adhere to the specification of the MUSIC
+interface in order to communicate with other applications performing
+complementary tasks.  This makes the development of MUSIC-aware
+software independent of what other applications it will communicate
+with.
+
+We hope that this will facilitate the development of general purpose
+tools.  For example, a researcher can develop a tool for calculating
+synthetic EEG from simulation data.  Via MUSIC, this tool should then
+be useful for anybody using any neuronal simulator which supports the
+common MUSIC interface.
+
+
+\subsection{Performance}
+
+The MUSIC API has been designed to allow for data transport of high
+bandwidth and low latency within the cluster.  One means of ensuring
+the best use of the hardware while maintaining portability is to use
+the facilities of MPI for communication.  MPI encapsulates software
+optimizations for specific hardware. By basing the interface on MPI we
+can benefit from such optimizations.
+
+
+\subsection{Extensibility}
+
+Where possible, MUSIC allows for extensions by the application
+programmer.  Some classes in the MUSIC API (such as the index and data
+maps) can be subclassed in order to provide facilities not available
+directly in the API.
+
+
+\section{Terminology}
+
+\begin{description}
+\item[application] We use the term
+  \emph{application}\index{application} to denote a simulator or other
+  program interfaced to MUSIC.  Each application is a parallel
+  program, normally running on several processors.
+
+\item[multi-simulation] We use the term
+  \emph{multi-simulation}\index{multi-simulation} to refer to the
+  whole parallel execution of multiple applications coordinated by
+  MUSIC.
+
+\item[port] Each application declares its ability to produce and
+  consume data by publishing \emph{ports}\index{port}.  Ports are
+  named by the application and provided with information about the
+  datatype (continuous data, spike events, messages) and mapping onto
+  different processors.  Ports are either
+  \lstinline|InputPort|s\index{input port} or
+  \lstinline|OutputPort|s\index{output port}.
+
+\item[connection] During the setup phase, MUSIC connects pairs of
+  ports together to form \emph{connections}\index{connection}.  During
+  the runtime phase, data is transferred over the connection from the
+  producer of the data to the consumer.  While an
+  \lstinline|InputPort| can have only one connection, an
+  \lstinline|OutputPort| can be connected to multiple
+  \lstinline|InputPort|s.
+
+\item[data map] A data map\index{data map} denotes the information on
+  where data actually resides within the application.  This is
+  typically stored internally in the port data structure.  Data to be
+  transferred over a connection can be regarded as a large array
+  distributed over multiple processors.  The data map tells on
+  what processor each data element resides and how it should be
+  accessed.
+
+\item[ticks] During the runtime phase, all processes in each
+  application must make a \emph{tick}\index{tick} call at regular
+  intervals in simulated time.  At these tick points, MUSIC is allowed
+  to use MPI to transfer data between processors.
+\end{description}
+
+
+\section{Relation to Existing Software}
+
+MUSIC is not the only software project aiming to support
+inter-operability between neural simulators.  In this section we will
+briefly describe some related projects and specifically focus on how
+they relate to MUSIC.
+
+\paragraph{PyNN}\index{PyNN}
+
+PyNN is a Python package for simulator-independent specification of
+neuronal network models.  It provides a low-level procedural API and a
+high-level object-oriented API.  Neuronal network models which are
+specified using these API:s can be simulated on simulators supporting
+PyNN, such as Neuron\index{Neuron} and NEST\index{NEST}.
+
+PyNN could be extended to support multi-simulations using the MUSIC
+library.  Such an extension would provide means for controlling the
+interaction between the simulator and the MUSIC library and would, for
+example, support publishing of named ports.
+
+It is possible, in principle, to write Python code to directly handle
+communication between applications in a cluster, but such a solution
+would be inefficient compared to using MUSIC, and might, in the end,
+have to address the same problems which MUSIC provides a solution to.
+
+\paragraph{Neurospaces}\index{Neurospaces}
+
+The Neurospaces project promotes inter-operability and re-usability
+through the development of independent software components, some of
+which, together, will provide one of two alternative cores of the
+Genesis 3 simulator.  One of the components, the Neurospaces Model
+Container abstracts model description from the solver.  Another
+component, the Discrete Event System can handle distribution and
+queuing of spikes.  Components adhere to the CBI simulator
+architecture.
+
+It is possible to develop a MUSIC adapter consistent with the CBI
+simulator architecture.  This would allow the Neurospaces framework,
+and Genesis 3, to interface to independently running applications in a
+cluster environment.
+
+\begin{metatext}
+\paragraph{Neosim}\index{Neosim}
+
+\paragraph{MOOSE}\index{MOOSE}
+\end{metatext}
+
+\chapter{Execution Model}
+
+\section{Phases of Execution}
+
+A multi-simulation, i.e. a set of interconnected parallel
+applications, is executed in three distinct phases:
+\begin{description}
+\item[\textbf{Launch}]\index{launch phase} is the phase where all the
+  applications are started on the processors.  During this phase,
+  MUSIC is responsible for distributing and launching the application
+  binaries on the set of MPI processes allocated to the MUSIC job.
+  Since MPI can be initialized first when the applications have been
+  launched, most of this work needs to be performed outside of MPI.
+  In particular, the tasks of accessing the command line argument of
+  the MUSIC launch utility and of determining the ranks of processes
+  before MPI initialization therefore has to be handled separately for
+  different MPI implementations.
+
+  Technically, the launch phase begins when \texttt{mpirun} launches
+  the MUSIC binary and ends when the Setup object constructor
+  returns.  (See further description below.)
+
+\item[\textbf{Setup}]\index{setup phase} is the phase when all
+  applications can publish what ports they are prepared to handle
+  along with the time step they will use and where data will be
+  present (where in memory and/or on what processor).  During the
+  setup phase, applications can read configuration parameters
+  communicated via the common configuration file.  At the end of the
+  setup phase, MUSIC will establish all connections.
+
+  The setup phase begins when the Setup object has been created and
+  ends when the runtime object constructor returns.
+
+\item[\textbf{Runtime}]\index{runtime phase} is the phase when
+  simulation data is actually transferred between applications.  Via
+  \texttt{tick} calls the simulated time of applications is
+  kept in order.
+
+  The runtime phase begins when the runtime object has been created
+  and ends when its finalize method is called.
+\end{description}
+
+From the application programmers point of view, these phases are
+clearly separated through the use of two main components of the
+MUSIC interface: the \emph{Setup} and the \emph{Runtime} object.  The
+launch phase is not visible for the application since it handles the
+situation before the application starts.
+
+When the application initializes MUSIC at the beginning of execution
+it receives a specific \emph{Setup object}.  This object gives access
+to the functionality relevant during the setup phase via its methods.
+When done with the setup, the application program makes the transition
+to the runtime phase by passing the Setup object as an argument to the
+\emph{runtime object} constructor which destroys the Setup object.
+The runtime object provides methods relevant during the runtime phase
+of execution.
+
+\section{Spatial Distribution of Data}
+\label{sec:spatialdist}
+
+Communication between applications is handled by ports.  Ports are
+named sources (output ports) or sinks (input ports) of data flows.
+The data to be communicated may be differently organized in process
+memory on the receiver side compared to the sender side.  The
+applications may run on different numbers of processes, and, the data
+may be differently distributed among the sender processes and the
+receiver processes, as is shown in Figure~\ref{fig:datamapping}.  How
+does MUSIC know which data to send where?
+
+In MUSIC, there are two views of the data to be communicated over a
+connection.  Data elements are enumerated differently according to
+these views.  MUSIC uses \emph{shared global indices}\index{shared
+  index}\index{global index} to enumerate the entire set of data to be
+sent over the connection while \emph{local indices}\index{local index}
+enumerate the subset of data which is stored in the memory of a
+particular MPI process.  Data does not need to be ordered in the same
+way according to the two views.  For example, data stored in an array
+may be associated with an arbitrary subset of global indices in an
+arbitrary order.
+
+The MUSIC library is informed about the relationship between global
+and local indices and how data is stored in memory during the setup
+phase.  Two abstractions are used to carry this information:
+
+The \lstinline|IndexMap| maps local indices to global indices.  That
+is, the \lstinline|IndexMap| tells which parts of a distributed data
+array are handled by the local process and how the data elements are
+locally ordered.
+
+The \lstinline|DataMap| encapsulates how a port accesses its data.
+The \lstinline|DataMap| contains an \lstinline|IndexMap|.  While an
+index map is a mapping between two kinds of indices, the data map also
+contains information about where in memory data resides, how it is
+structured, and, the type of the data elements.  The type is used for
+marshalling when running on a heterogeneous cluster.
+
+During setup every process of the application individually provides
+the port with a \lstinline|DataMap| (or an \lstinline|IndexMap| in
+the case of event ports).
+
+\begin{figure}
+  \begin{center}
+    \includegraphics[width=0.7\textwidth]{figures/datamapping}
+    \caption[Mapping of data]{\label{fig:datamapping} Data transfer
+      over a connection from an application running in four processes
+      to an application running in three processes.  The light gray
+      areas in the sender and receiver represents the MUSIC port.
+      Dashed lines divide the application into distinct processes.  }
+  \end{center}
+\end{figure}
+
+\begin{rationale}
+  While connections are often used to handle the transfer of spikes
+  from one group of neurons to another, they should not be regarded as
+  an implementation of synaptic projections\index{projections}.
+  Connections will only handle a direct one-to-one transport from one
+  application to another.  Re-mapping to actual receiving neurons,
+  e.g. to implement an all-to-all projection, must be handled by one
+  of the applications.  Thus, it may be better to regard the ports as
+  \emph{proxy-objects}\index{proxy objects}, providing indirect access
+  to neurons simulated by the other application.
+\end{rationale}
+
+
+\section{Timing Considerations}
+\label{sec:timing}
+  
+Different applications may use different time steps and it is the
+responsibility of MUSIC to ensure that data is delivered at the
+appropriate time.  In order to minimize handshaking, both parts of a
+connection pair locally calculate when the actual data transfer over
+MPI takes place.  To ensure that these calculations produce
+predictable results, simulation time is internally represented using
+integers with a global micro-timestep\index{micro-timestep} common for
+all applications.
+
+Simulation time\index{simulation time} is local for each application
+and MUSIC does not enforce unnecessary synchronization between these
+local clocks.  Thus, an application producing data may be running
+ahead of another application which consumes the same data.  MUSIC
+internally builds a schedule which ensures that data arrives at the
+appropriate local time in the receiving application.  Scheduling
+becomes more complex when data is not only transferred in a
+feed-forward manner, i.e. when the connection graph contains loops.
+In this case MUSIC has to rely on the existence of sufficient delays
+in the simulated model, typically corresponding to axonal
+delays\index{axonal delay}.
+
+\begin{figure}
+  \begin{center}
+    \begin{minipage}{0.45\textwidth}
+      \includegraphics[width=\textwidth]{figures/ticklogic}
+      \caption[Timing of data transfer, slowdown]{\label{fig:timingshorter}
+        Transfer of data when sender has a shorter
+        tick interval than the receiver.}
+    \end{minipage}
+    \hfill
+    \begin{minipage}{0.45\textwidth}
+      \includegraphics[width=\textwidth]{figures/ticklogic2}
+      \caption[Timing of data transfer, speedup]{\label{fig:timinglonger}
+        Transfer of data when sender has a longer
+        tick interval than the receiver.}
+    \end{minipage}
+  \end{center}
+\end{figure}
+
+Figures~\ref{fig:timingshorter} and \ref{fig:timinglonger} illustrate
+how MUSIC handles time when transferring continuous data over a
+connection.  In figure~\ref{fig:timingshorter}, the sender application
+uses a shorter tick interval than the receiver.  The sender side uses
+values sampled at the tick points to interpolate a value corresponding
+to the point in time when the receiver makes its tick call.
+
+The dark middle area (labelled ``MPI'') is where the actual data
+transfer takes place.  MUSIC makes use of the fact that the receiving
+application can run with its simulation clock set independently of the
+sender.  The arrows going ``backwards in time'' in this area reflect
+the fact that the receivers clock is lagging.  This makes it possible
+for data to arrive in time despite the fact that it was available
+later (e.g. at tick \(s_2\)) than when it was arriving (at \(r_1\)),
+when talking about simulated time.
+
+Figure~\ref{fig:timinglonger} illustrates what happens when the
+receiver of continuous data is calling tick faster then the sender.
+The sender will then buffer up values from the preceding and current
+ticks and transfer this at a suitable tick call.  The receiver will
+portion these values out by interpolating at the appropriate ticks.
+
+The strategy of having the receiver application running with a delayed
+local clock only works when the connection graph forms a directed
+acyclic graph (DAG)\index{DAG}\index{acyclic graph}\index{loops}.
+When loops occur it is necessary to allow for data arriving late, at
+least somewhere along each loop.  MUSIC handles this via
+\emph{acceptable latency}\index{acceptable latency}\index{latency}
+which is a property of event input ports.  The receiving application
+declares how late, according to simulation time, data may arrive, thus
+giving MUSIC room for resolving the scheduling problem.  In the case
+of continuous data, the application specifies a
+\emph{delay}\index{delay} which fulfills the same purpose.
+
+In figures \ref{fig:timingshorter} and \ref{fig:timinglonger}, the
+sending application must be running ahead of the receiver in order to
+maintain the illusion that communication is instantaneous.
+Figure~\ref{fig:timeline} illustrates the timing relation between
+sender and receiver along a real time axis (wallclock time) when the
+receiver accepts a delay of incoming data.  This allows the receiver
+(B) to run ahead of the sender (A), thus creating the slack necessary
+to make schedules for communication loops.
+
+\begin{figure}
+  \begin{center}
+    \includegraphics[width=0.7\textwidth]{figures/timeline}
+    \caption[Timing of ticks]{\label{fig:timeline}
+      This figure illustrates how MUSIC can allow one application (B)
+      to execute ahead of another (A) when transferring continuous
+      data.  The receiver (B) has specified a delay on the input port
+      which means that the value to be delivered at each tick (gray
+      areas) corresponds to a simulated time in A (blue arrows) which
+      has already happened.
+
+      Note that the tick times when MUSIC actually transfers data will
+      be aligned on the real time axis, since blocking communication
+      is used.  In practice, one of the applications will have to wait
+      for the other to reach the same point in its execution.
+    }
+  \end{center}
+\end{figure}
+
+
+\section{Message Ports}\index{message port}
+
+In addition to the port types which handle continuous and spike event
+data, MUSIC provides \emph{message ports}.  Message ports allow for
+transmission of arbitrary messages of, for example, control
+information between applications.  A multi-simulation may, for
+example, be controlled by a script running in a Python process on one
+of the cluster nodes.  The script may use a message port to alter a
+parameter or turn on a stimulus in an application at a certain point
+in time.
+
+Messages sent from any process on the sender side of the connection
+are routed to all processes on the receiver side which have announced
+there willingness to receive messages.  Contrary to ports for
+continuous data, any marshalling is the responsibility of the sender
+and receiver application.
+
+To achieve independence between MUSIC applications, it is recommended
+that messages are text strings with the syntax of the interpreter
+language of the receiving application, and that these text strings
+originate from a user-specified configuration file read by the sending
+application.
+
+
+\section{Application Responsibilities}
+
+One goal of MUSIC has been to limit the responsibilities imposed on
+each application (c.f. section \ref{sec:simplicity}).  Here we present
+a step-by-step list of what an application must do in order to
+participate in a multi-simulation.
+
+\begin{enumerate}
+\item \textbf{Initiate MUSIC}\index{initiate MUSIC}
+
+  This is done by calling the \lstinline!Setup! function.
+\item \textbf{Create ports}
+
+  Data to be imported and exported is identified by creating named
+  ports.
+\item \textbf{Map ports}\index{map ports}
+
+  MUSIC is informed about where the actual data is located.  This
+  includes information about which processor owns each data element.
+  For continuous data it also includes information about where in
+  memory it is stored, while for event data it specifies how to
+  receive events.
+\item \textbf{Initiate the runtime phase}
+
+  At this stage, MUSIC can build the plan for communication between
+  different processes.
+\item \textbf{Advance simulation time}\index{tick}\index{advance time}
+  \index{time}
+
+  The application must call \lstinline!tick! at regular intervals
+  to give MUSIC the opportunity to transfer data.
+\item \textbf{Finalize MUSIC}\index{finalize}\index{terminate}
+
+  By calling \lstinline|finalize|, all MUSIC communication is terminated.
+\end{enumerate}
+
+
+\chapter{Starting a Multi-Simulation}
+
+\section{Overview}
+
+Parallel programs based on MPI are normally started by running a
+special program called \texttt{mpirun}\index{mpirun} (for MPI-1) or
+\texttt{mpiexec}\index{mpiexec} (for MPI-2).  To start multiple
+applications and enable them to communicate with each other, MUSIC
+utilizes a special launcher program called \texttt{music}\index{music
+  (launcher)} which, in turn, starts the different applications.
+Information about which applications should be started, and the
+communication pattern between them is described in a common
+\emph{configuration file}\index{configuration file}.
+
+\begin{rationale}
+  The reason for not controlling configuration via the MUSIC API is
+  that individual applications should remain ignorant about the
+  structure of the full multi-simulation.  Thus, the API provides
+  methods for asking about the parts of the configuration relevant for
+  that application, i.e. its ports, but does not expose the complete
+  communication graph.
+\end{rationale}
+
+
+\section{The Configuration File}
+
+The main purpose of the configuration file is to control what
+applications to start, and to connect output ports to input ports.
+The configuration file specifies the number of MPI processes allocated to
+each application.
+
+The configuration file consists of a sequence of blocks, each starting
+with a non-indented bracket:
+
+\begin{quote}
+  [\emph{application\_label}]
+\end{quote}
+
+\noindent Each block consists of a sequence of configuration variable
+definitions applying to one application.  The application label is
+used to refer to ports of the application.  A variable definition
+takes the form of an assignment:
+
+\begin{quote}
+  \emph{varname} = \emph{value}
+\end{quote}
+
+The following variable names have special meaning to MUSIC:
+\begin{description}
+  \item[binary] Pathname to application binary
+  \item[args] Command line given to the binary
+  \item[np] The number of MPI processes to allocate for the application
+  \item[timebase] The length of a MUSIC micro-step, that is, the
+    resolution of {MUSIC}:s internal clocks).  (Default value is 1
+    ns.)
+\end{description}
+\begin{rationale}
+  The possibility to specify the MUSIC timebase is provided since the
+  timebase is a compromise between resolution and maximal simulation
+  time.  With 64-bit clocks, a timebase of 1 ns gives a maximal
+  simulation time of 585 years which should be sufficient for most
+  applications.
+\end{rationale}
+
+Arbitrarily named parameters may also be included in the configuration
+file and these parameters can be accessed from the applications.
+
+A connection between an output and input port is specified using the
+following syntax:
+\begin{quote}
+  \emph{application\_label.port\_name} \lstinline|->| \emph{application\_label.port\_name}
+\end{quote}
+\noindent  The direction of the arrow (\lstinline|->|, \lstinline|<-|) indicates the
+direction of data transport.  An output port can be connected to
+multiple input ports while an input port can be connected to, at most,
+one output port.
+
+Optionally, the width of the connections between applications can be
+specified:
+\begin{quote}
+  \emph{application\_label.port\_name} \lstinline|->|
+  \emph{application\_label.port\_name} [\emph{width}]
+\end{quote}
+The application label can be omitted if it refers to the application
+being specified by the surrounding block.
+An example of a simple configuration file can be seen in
+section~\ref{sec:conffile}.  Appendix~\ref{sec:specsyntax} specifies
+the formal syntax of configuration files.
+
+\begin{rationale}
+  Information from the configuration file needs to be available both
+  in order to launch the application binaries and during the setup
+  phase.  Since launching must be done prior to MPI initialization, it
+  is not possible to distribute configuration information via MPI
+  itself.  In the reference implementation of MUSIC, environment
+  variables are used to distribute this information to the
+  applications.
+
+  This information transfer is hidden within MUSIC, so a different
+  implementation of MUSIC may use another technique.  In particular,
+  if the applications are launched from a scripting program, such as
+  PyNN\index{PyNN}, that program must also take care of transferring
+  the relevant configuration information to the applications.
+\end{rationale}
+
+
+\chapter{Application Program Interface}
+
+\section{Conventions}
+
+This chapter describes the API to the MUSIC library.  The API is
+object oriented and all communication with the library is performed
+via instance methods of different classes of objects.  Appendix
+\ref{app:cint} presents an alternative C interface.  The most common
+way of passing objects as arguments in MUSIC is via pointers.  The
+only exception is the Setup constructor.  The convention regarding
+memory management is that the caller should make sure that objects
+exist in memory during the entire execution of the method, and is also
+responsible for the deallocation of objects afterwards.
+
+
+\section{Error handling}
+
+MUSIC attempts to fall back on the error handling mechanisms of MPI.
+A MUSIC exception thus results in a call to the MPI error handler.
+A particular implementation of the MUSIC library does not guarantee
+that it handles all kinds of errors that may occur during MUSIC calls.
+Each error handled by MUSIC generates an exception, and MUSIC installs
+suitable error codes, classes and strings so that the MPI error
+handler is able to generate suitable error messages.
+
+MUSIC follows the style of error handling in the MPI standard, which
+is described in sections 7.2 and 7.3 in the MPI 1.1
+report\cite{mpi1.1} and in section 2.8 of the MPI 2.0
+report\cite{mpi2.0}.  The default error handler of MPI is
+\lstinline|MPI_ERRORS_ARE_FATAL| which means that any error handled by
+MUSIC will result in the program being aborted.  Using the error
+handling of MPI requires features only described in the MPI 2.0
+report.  For MPI implementations which lack this support, MUSIC uses
+its own error handler which has the same behavior as
+\lstinline|MPI_ERRORS_ARE_FATAL|.
+
+\begin{rationale}
+  MUSIC adheres to the error handling strategy of MPI since the
+  application is already using MPI and should not need to implement a
+  second error handling strategy when converted to use MUSIC.
+\end{rationale}
+
+\section{Setup}
+
+\subsection{The setup constructor}
+
+Each application initializes the MUSIC library through a call to the
+Setup constructor\index{setup}.  This constructor, in turn, calls
+\lstinline|MPI::Init|\index{MPI::Init}\index{init} to initialize
+MPI\index{initialize MPI}.  The Setup constructor creates the Setup
+object through which the application can retrieve configuration
+information, get an application wide communicator, and setup ports.
+
+\begin{head}{Setup}
+  Setup::Setup (int& argc, char**& argv)
+\end{head}
+\begin{parameters}
+  \lstinline|argc| &%
+  reference to the \lstinline|argc| argument of \lstinline|main| \\
+  \lstinline|argv| &%
+  reference to the \lstinline|argv| argument of \lstinline|main| \\
+\end{parameters}
+
+This constructor must be called at most once; subsequent calls are
+erroneous.  It accepts the \lstinline|argc| and \lstinline|argv| that are
+provided by the arguments to \lstinline|main|.
+\index{argc}\index{argv}
+
+\begin{code}{Initializing MUSIC}
+int main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+
+  /* parse arguments */
+  /* rest of program */
+}
+\end{code}
+
+\begin{rationale}
+  The idea behind creating a specific setup object is to ensure that
+  the application does not accidentally call functions relevant only
+  for the setup phase at other times.
+\end{rationale}
+
+
+\subsection{Communicators}
+
+During a multi-simulation the MUSIC library will create a unique
+intra-communi\-cator over the group of processes assigned to each
+application.  This application wide communicator takes the role of the
+global communicator \lstinline|MPI::COMM_WORLD| and is retrieved from
+the setup object through a call to the \lstinline|communicator|
+method.\index{communicator}
+
+\begin{head}{communicator}
+  MPI::Intracomm Setup::communicator ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & the application wide communicator \\
+\end{parameters}
+
+The application is supposed to use the application wide communicator
+in place of
+\lstinline|MPI::COMM_WORLD|\index{MPI::COMM\_WORLD}\index{COMM\_WORLD}. If
+the application binary has been launched using \lstinline|mpirun|
+instead of the \lstinline|music| utility, \lstinline|communicator ()|
+will return \lstinline|MPI::COMM_WORLD| as the application wide
+communicator.
+
+\pagebreak
+\index{rank}\index{Get\_rank}
+\begin{code}{Accessing the application-wide communicator}
+/* communicator with global scope */
+extern MPI_Comm comm;
+
+...
+{
+  ...
+  comm = setup->communicator ();
+  int rank = comm.Get_rank ();
+  ...
+}
+\end{code}
+
+\begin{rationale}
+  An alternative to provide the \lstinline|communicator| function
+  would have been to redefine \lstinline|MPI::COMM_WORLD|.  This would
+  ensure that an application does not accidentally use the global
+  communicator.  However, it may not always be possible to dynamically
+  redefine this variable in all MPI implementations, so for the sake
+  of portability, we have chosen a more straightforward technique.
+\end{rationale}
+
+
+\subsection{Port creation}
+
+Ports\index{ports} are named sources (output ports) or sinks (input
+ports) of data flows.  Output and input ports are distinct classes.
+Ports are further subdivided into distinct classes depending on
+whether they handle continuous data, event data or messages.
+
+\index{publish output}\index{publish input}
+\begin{head}{publishContOutput,publishContInput,
+            ,publishEventOutput,publishEventInput,
+            ,publishMessageOutput,publishMessageInput}
+  ContOutputPort*
+  Setup::publishContOutput (string id)
+
+  ContInputPort*
+  Setup::publishContInput (string id)
+
+  EventOutputPort*
+  Setup::publishEventOutput (string id)
+
+  EventInputPort*
+  Setup::publishEventInput (string id)
+
+  MessageOutputPort*
+  Setup::publishMessageOutput (string id)
+
+  MessageInputPort*
+  Setup::publishMessageInput (string id)
+\end{head}
+\begin{parameters}
+  \lstinline|id| & port name \\
+  \emph{return value} & an unmapped port \\
+\end{parameters}
+
+Ports have two stages in life: the \emph{unmapped} stage and the
+\emph{mapped} stage.  A port is unmapped when created.  The MUSIC
+configuration file specifies connections between ports.  It is
+possible to ask an unmapped port if it is connected, if it has a width
+specified and, if so, what width it has.  A port becomes mapped when
+its method \lstinline|map| is called.
+
+\begin{code}{Creating an unmapped port}
+ContOutputPort* out =
+   setup->publishContOutput ("out");
+\end{code}
+
+\subsection{General port methods}
+
+The port API includes methods to ask a port if it is connected, if it
+has a width specified, and, if so, what that width is.
+
+\subsubsection{Port connectivity}
+
+The method \lstinline|isConnected| is used to check if the user has
+specified a connection of this port to another port in the
+configuration file.
+
+\index{isConnected}\index{connected port}
+\begin{head}{isConnected}
+  bool Port::isConnected ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & \lstinline|true| only if connected\\
+\end{parameters}
+
+This method is typically used in cases where the use of some of the
+ports of the application is optional.  In such a case, it is not
+sensible to allocate any application resources to support the data
+flow in question.  One example is if one wants to support output of
+membrane potentials from a certain population of cells, but don't want
+to waste resources if no one is listening.
+
+\begin{code}{Optional handling of ports}
+ContOutputPort* out =
+   setup->publishContOutput ("Vm");
+/* map port only if anyone is listening */
+if (out->isConnected ())
+  /* allocate application resources and map port */
+\end{code}
+
+\subsubsection{Port width}
+\label{sec:width}
+
+The width of a port\index{port width}, that is the number of data
+elements transferred in parallel from a cont port or the largest
+possible id of an event port $+$ 1, can be specified in the
+configuration file.  This should be thought of as a request for a
+given width.  Applications can use the method \lstinline|hasWidth| to
+determine if a width has been specified and retrieve it using
+\lstinline|width|.  Message ports do not have width.
+
+\index{hasWidth}
+\begin{head}{hasWidth}
+  bool Port::hasWidth ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & \lstinline|true| only if port width has been
+                         specified \\
+\end{parameters}
+
+\index{width}
+\begin{head}{width}
+  int Port::width ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & port width \\
+\end{parameters}
+
+\begin{rationale}
+  Applications can use the above methods to adapt their port width.  A
+  typical usage would be a general purpose post-processing tool which
+  receives information from an ongoing simulation.  Such a tool can
+  publish a number of optional input ports and then use
+  \lstinline|isConnected| and \lstinline|width| to adapt its internal
+  processing depending on what kind of data source it is actually
+  connected to.  See example \ref{code:adaptivewidth}.
+\end{rationale}
+
+
+\begin{code}{Publishing port of adaptive width\label{code:adaptivewidth}}
+{
+  ...
+  /* Publishing a port of adaptive width */
+  double* stateVars;
+  MUSIC::ContInputPort* in =
+     setup->publishContInput ("in");
+  if (!in->hasWidth ())
+    /* report error */
+  else
+    {
+      int size = in->width ();
+      /* for clarity we assume that nElements
+         is a multiple of size */
+      int nLocal = nElements / size;
+      /* example continues as in next example */
+      ...
+      
+    }
+}
+\end{code}
+
+
+\subsection{Mapping cont ports}
+\index{cont ports}
+
+A port is informed about what data exists locally and how to access it
+by mapping it.  Cont ports transfer data from or to memory during
+\lstinline|tick| calls and need to know the layout of data in memory.
+In addition, the marshalling (conversion between different bit level
+representations) performed on heterogeneous clusters requires
+information about the data type being transferred.  This information
+is captured by the data map argument \lstinline|dMap|.  The
+\lstinline|DataMap| type is described in section \ref{sec:datamap}
+below.
+
+\clearpage
+\index{map}\index{mapping cont ports}
+\begin{head}{map}
+  void ContOutputPort::map (DataMap* dMap,
+                            int maxBuffered)
+
+  void ContInputPort::map (DataMap* dMap,
+                           double delay,
+                           int maxBuffered,
+                           bool interpolate)
+\end{head}
+\begin{parameters}
+  \lstinline|dMap| & the data map associated with the port \\
+  \lstinline|delay| & delay of data arrival in simulation time (s) \\
+  \lstinline|maxBuffered| & maximal amount of data buffered (ticks)
+  \\
+  \lstinline|interpolate| & enable interpolation (boolean) \\
+\end{parameters}
+
+The optional argument \lstinline|delay| informs MUSIC of when,
+according to simulation time, to sample data on the sender side.  If
+enabled, linear interpolation is used to obtain an approximation of
+the state at this time.  The default delay is zero.  Delayed continuous
+data may be used in connectionist networks when modeling brain
+pathways.  A delay is \emph{required} at some point when communicating
+continuous data in a loop (c.f. section \ref{sec:timing}).
+
+Buffering data in output and input ports gives more efficient
+communication since data can be sent fewer times in larger packets.
+By default MUSIC buffers some reasonable amount of data.  In certain
+situations it is necessary to be careful about memory usage.  Using
+the optional argument \lstinline|maxBuffered| the application can
+give MUSIC a bound on how much data to buffer.  MUSIC decides how much
+data to buffer based on the lowest \lstinline|maxBuffered| parameter
+given when mapping each of a set of connected ports and on latency
+considerations when applications are connected in loops.  A
+\lstinline|maxBuffered| value of \(N\) ticks means: don't buffer more
+data than is sufficient for communicating at every \(N\)\,th tick.
+
+When the optional argument \lstinline|interpolate| is
+\lstinline|true|, MUSIC uses linear interpolation to determine the
+values delivered on the receiver side.  This is the default behavior.
+By passing \lstinline|false| this interpolation can be switched off in
+which case MUSIC selects the sample on the sender side which is
+closest according to simulation time.
+
+\clearpage
+\begin{code}{Mapping ports to internal data\label{code:mapping}}
+{
+  ...
+  int size = comm.Get_size ();
+  int rank = comm.Get_rank ();
+  /* for clarity we assume that nElements
+     is a multiple of size */
+  int nLocal = nElements / size;
+  double* stateVars = new double[nLocal];
+  MUSIC::ContInputPort* out =
+     setup->publishContOutput ("out");
+  MUSIC::ArrayData dMap (stateVars, MPI::DOUBLE,
+                         rank * nLocal, nLocal);
+  out->map (&dMap);
+  ...
+}
+\end{code}
+
+
+\subsection{Mapping event ports}
+\index{event ports}
+
+\index{map}\index{mapping event ports}
+\begin{head}{map}
+  void EventOutputPort::map (IndexMap* indices,
+                             Index::Type type,
+                             int maxBuffered)
+
+  void EventInputPort::map (IndexMap* indices,
+                            EventHandler* handleEvent,
+                            double accLatency,
+                            int maxBuffered)
+\end{head}
+\begin{parameters}
+  \lstinline|indices| & the index map associated with the port \\
+  \lstinline|type| & the indexing type used (local or global) \\
+  \lstinline|handleEvent| & a user-defined event handler \\
+  \lstinline|accLatency| & acceptable latency for incoming data (s) \\
+  \lstinline|maxBuffered| & maximal amount of data buffered (ticks) \\
+\end{parameters}
+
+Since event ports don't access data the same way as cont ports, they
+do not require a full \lstinline|DataMap|.  Instead, an
+\lstinline|IndexMap| is used to describe how indices in the
+application should be mapped to the shared global indices common for
+sender and receiver.  The applications has the choice of using local
+indices or bypassing the index transformation by directly using the
+shared global indices when labelling events.  This is controlled by
+the \lstinline|type| parameter which can be set to
+\lstinline|MUSIC::Index::LOCAL| or \lstinline|MUSIC::Index::GLOBAL|.
+
+Events are communicated to the application through an \emph{event
+  handler}\index{event handler}.  The event handler is called by MUSIC
+when the application calls \lstinline|tick|.  It is called once for
+every event delivered.
+
+Some spiking neural network models include axonal delays.  The MUSIC
+framework assumes that handling and delivery of delayed spikes occurs
+on the receiver side.  In such a case, the receiver may allow MUSIC to
+deliver a spike event later than its time stamp according to local
+time.  The maximal acceptable latency is specified through the
+\lstinline|accLatency|\index{accLatency} argument.
+
+The optional argument \lstinline|maxBuffered|\index{maxBuffered}
+has a similar meaning as for cont ports above but the actual amount
+of data buffered is, in this case, not deterministic since it is
+dependent on spike rate.
+
+
+\subsubsection{Sending events}
+\index{sending events}
+
+The sender registers events for transmission by calling the method
+\lstinline|insertEvent|.
+
+\index{insertEvent}
+\begin{head}{insertEvent}
+  void EventOutputPort::insertEvent (double t,
+                                     LocalIndex id)
+  void EventOutputPort::insertEvent (double t,
+                                     GlobalIndex id)
+\end{head}
+\begin{parameters}
+  \lstinline|t| & trigger time of the event (s) \\
+  \lstinline|id| & the local or global index of the event \\
+\end{parameters}
+
+MUSIC guarantees that this event will be delivered through a call to
+the user-specified \lstinline|EventHandler| on the receiver side no
+later that the acceptable latency relative to receiver local time.
+The time \lstinline|t| must be between the simulation time of the last
+tick and that of the next.
+
+The parameter \lstinline|id| should be converted from \lstinline|int|
+to \lstinline|LocalIndex| or \lstinline|GlobalIndex| to indicate what
+kind of indices are used in the application.
+
+
+\subsubsection{Receiving events}
+\index{receiving events}
+
+\index{EventHandler}
+\begin{head}{EventHandlerLocalIndex,EventHandlerGlobalIndex,operator}
+  class EventHandlerLocalIndex {
+  public:
+    virtual void operator () (double t,
+                              LocalIndex id) = 0;
+  };
+
+  class EventHandlerLocalIndex {
+  public:
+    virtual void operator () (double t,
+                              GlobalIndex id) = 0;
+  };
+\end{head}
+\begin{parameters}
+  \lstinline|t| & trigger time of the event (s) \\
+  \lstinline|id| & local or global index if the event \\
+\end{parameters}
+
+Event handlers are called by event input ports to deliver events.  The
+application is supposed to customize either
+\lstinline|LocalEventHandler| or \lstinline|GlobalEventHandler| by
+subclassing one of them (depending on the indexing
+scheme the application uses).
+
+
+\clearpage
+\subsection{Mapping message ports}
+\index{message ports}
+
+Message ports behave similarly to event ports in that messages are
+sent and delivered using similar mechanisms, but while events are
+routed between processes based on event indices, messages are routed to all
+processes on the receiver side which have provided a
+\lstinline|MessageHandler| to \lstinline|map|.  All arguments to
+\lstinline|map| for message ports are optional.
+
+\index{map}\index{mapping message ports}
+\begin{head}{map}
+  void MessageOutputPort::map (int maxBuffered)
+
+  void MessageInputPort::map (MessageHandler* handler,
+                              double accLatency,
+                              int maxBuffered)
+\end{head}
+\begin{parameters}
+  \lstinline|handler| & a user-defined message handler \\
+  \lstinline|accLatency| & acceptable latency for incoming data (s) \\
+  \lstinline|maxBuffered| & maximal amount of data buffered (ticks) \\
+\end{parameters}
+
+
+\subsubsection{Sending messages}
+\index{sending messages}
+
+The sender registers a message for transmission by calling the method\\
+\lstinline|insertMessage|.
+
+\index{insertMessage}
+\begin{head}{insertMessage}
+  void MessageOutputPort::insertMessage (double t,
+                                         void* msg,
+                                         size_t size)
+\end{head}
+\begin{parameters}
+  \lstinline|t| & time stamp (s) \\
+  \lstinline|msg| & pointer to message \\
+  \lstinline|size| & size of message in bytes \\
+\end{parameters}
+
+MUSIC will deliver this message through a call to the user-specified \\
+\lstinline|MessageHandler| on the receiver side no later than
+\lstinline|accLatency| with regard to the time stamp.
+
+\begin{code}{Sending a message}
+{
+  ...
+  char m[] = "string to send";
+  port->insertMessage (runtime->time (), m, sizeof (m));
+  ...
+}
+\end{code}
+
+\pagebreak
+\subsubsection{Receiving messages}
+\index{receiving messages}
+
+\begin{head}{MessageHandler,operator}
+  class MessageHandler {
+  public:
+    virtual void operator () (double t,
+                              void* msg,
+                              size_t size) = 0;
+  };
+\end{head}
+\begin{parameters}
+  \lstinline|t| & time stamp supplied by sender (s) \\
+  \lstinline|msg| & pointer to message subclass instance \\
+  \lstinline|size| & size of message instance in bytes \\
+\end{parameters}
+
+Message handlers are called by message input ports to deliver
+messages.  The application is supposed to customize
+\lstinline|MessageHandler| by subclassing.  It is recommended that
+messages are text strings with the syntax of the interpreter language
+of the receiving application, and that these text strings originate
+from a user-specified configuration file read by the sending
+application.
+
+The message given to the \lstinline|MessageHandler| is deallocated by
+the MUSIC library.
+
+
+\subsection{Index maps}
+\index{index maps}
+
+An \lstinline|IndexMap| is a mapping from the local data element
+indices to shared global indices.  An index map instance thus holds
+information of which subset of the shared global indices belong to the
+local MPI process and of their local order.  MUSIC implements two
+subclasses of \lstinline|IndexMap|: \lstinline|PermutationIndex| and
+\lstinline|LinearIndex|.  The most general form is
+\lstinline|PermutationIndex| which allows for an arbitrary mapping.
+
+\index{PermutationIndex}
+\begin{head}{PermutationIndex}
+  PermutationIndex::PermutationIndex (int* indices,
+                                      int size)
+\end{head}
+\begin{parameters}
+  \lstinline|indices| & vector of shared indices \\
+  \lstinline|size| & number of shared indices \\
+\end{parameters}
+
+\index{LinearIndex}
+\begin{head}{LinearIndex}
+  LinearIndex::LinearIndex (int baseIndex, int size)
+\end{head}
+\begin{parameters}
+  \lstinline|baseIndex| & shared index corresponding to local index zero \\
+  \lstinline|size| & number of contiguous indices in this process \\
+\end{parameters}
+
+When a cont output port is mapped it becomes associated with a set of
+state variables (or other data) in the memory of the sender.  When the
+receiver calls \lstinline|runtime::tick|, an estimate of the values
+of these variables are stored in a set of variables associated with an
+input port on the receiver side.  Similarly, an event output port is
+mapped to a set of event id:s.
+
+While the number of variables or id:s on the receiver side is always
+the same as on the sender side, the data can be distributed in
+different ways between MPI processes on the sender side compared to
+the receiver side.  In fact, sender and receiver may consist of
+different numbers of processes.
+
+Index maps are used in each MPI process to tell MUSIC how data is
+distributed and ordered by enumerating the shared indices
+represented by the process in local order.
+
+\subsection{Data maps}
+\label{sec:datamap}
+\index{data maps}
+
+A \lstinline|DataMap| encapsulates how a port accesses its data.
+While an index map is a mapping between two kinds of indices, the data
+map also contains information about where in memory data resides, how
+it is structured, and, the type of the data elements.
+\lstinline|ArrayData| is a subclass of \lstinline|DataMap| which
+describes arrays of data elements.  See example \ref{code:mapping}.
+
+\index{ArrayData}
+\begin{head}{ArrayData}
+  ArrayData::ArrayData (void* buffer, MPI_Datatype type,
+                        IndexMap* map)
+\end{head}
+\begin{parameters}
+  \lstinline|buffer| & data memory location \\
+  \lstinline|type|   & data type \\
+  \lstinline|map|    & index map \\
+\end{parameters}
+
+Since data organized in arrays is common, MUSIC provides a convenience
+form of the array data map constructor which also creates a linear
+index map:
+
+\begin{head}{ArrayData}
+  ArrayData::ArrayData (void* buffer,
+                        MPI_Datatype type,
+                        int  baseIndex,
+                        int size)
+\end{head}
+\begin{parameters}
+  \lstinline|buffer|    & data memory location \\
+  \lstinline|type|	& data type \\
+  \lstinline|baseIndex| & shared index of first local element \\
+  \lstinline|size|      & number of contiguous indices in this process \\
+\end{parameters}
+
+
+\subsection{Configuration variables}
+\index{configuration variables}
+
+The values of all variables defined in the configuration file can be
+queried using the method \lstinline|config|.
+
+\index{config}
+\begin{head}{config}
+  bool Setup::config (string name, string* result)
+
+  bool Setup::config (string name, int* result)
+
+  bool Setup::config (string name, double* result)
+\end{head}
+\begin{parameters}
+  \lstinline|name|     & variable name \\
+  \lstinline|result|  & pointer to location where result should go \\
+  \emph{return value} & true if value of correct type was found \\
+\end{parameters}
+
+Querying for a value of type \lstinline|int| or \lstinline|double|
+expects a value of the correct type, if defined in the configuration
+file.  If the variable is defined, but its value can't be translated
+into the correct type this causes an error condition.
+
+\begin{code}{Querying configuration variables}
+/* Retrieving the parameter gKCa
+   from configuration file */
+double gKCa;
+if (!config ("gKCa", &gKCa))
+  gKCa = 29.5e-9; // default value
+\end{code}
+
+\section{Runtime}
+
+\subsection{The runtime constructor}
+
+\begin{head}{runtime}
+  Runtime::Runtime (Setup* s, double h)
+\end{head}
+\begin{parameters}
+  \lstinline|s| & pointer to the Setup object \\
+  \lstinline|h| & simulated time increment at each tick (s) \\
+\end{parameters}
+
+Creation of the runtime object marks the transition from the setup to
+the runtime phase.  The runtime object constructor destroys the Setup
+object, effectively making it impossible to create new ports.  All
+data structures which have been associated with ports during mapping
+must be initialized to some suitable start value at the time of the
+call to the runtime constructor.  These values are used during early
+data transfers of data sampled at negative values of simulation time
+and, thus, not available.
+
+\begin{code}{Runtime}
+...
+MUSIC::Runtime runtime = MUSIC::Runtime (setup, stepSize);
+...
+\end{code}
+
+\begin{rationale}
+  The step size is given as a real number (in seconds) since this
+  makes most sense from the applications point of view.  Internally,
+  this number is converted to an integer (using the time micro step
+  time base).  This is made to ensure that all processes use exactly
+  the same numbers even when the multi-simulation is running on mixed
+  architectures.  Both sides of a connection must agree on when data
+  is transferred over the MPI connector to minimize the
+  need for handshaking during the runtime phase.
+\end{rationale}
+
+\begin{rationale}
+  In order to create a deterministic schedule for buffering and data
+  transfer, we require that \lstinline|tick| increments simulated time
+  by a fixed amount each time.  We realize that some applications may
+  use a variable time step\index{variable time step} for their
+  numerical integrations, which may then make it harder to execute
+  these tick calls at the right time.  However, allowing variable tick
+  steps would have made it impossible to use a pre-computed
+  deterministic schedule and enforced repeated handshaking throughout
+  the runtime phase, resulting in a substantial performance
+  degradation.
+
+  Note that the tick step does not need to be equal to the internally
+  used integration step\index{integration step}.  We believe that most
+  large scale parallel simulators already have some means for fixed
+  interval operations, e.g. to handle logging to files or graphics,
+  which may be utilized also for the tick calls.
+\end{rationale}
+
+
+\subsection{The tick}
+\index{tick}
+
+\begin{head}{tick}
+  void Runtime::tick ()
+\end{head}
+\begin{parameters}
+\end{parameters}
+
+The tick function must be called at regular intervals in simulation
+time.  The application chooses the interval as a parameter to the
+\lstinline|Runtime| constructor, normally based on the time step used
+in the application.  The \lstinline|tick| function is typically called
+in the main simulation loop of each application.  Different
+applications may use different tick intervals and MUSIC will ensure
+that time is incremented consistently throughout the multi-simulation.
+
+Before \lstinline|tick| is called, the application must ensure that
+all data mapped for output is valid.  At the \lstinline|tick| call,
+time is incremented and data mapped for input is updated to reflect
+the new time.  Further, installed event handlers will be called
+\emph{during} the \lstinline|tick| call to deliver events.
+
+The MUSIC library may, or may not, exchange data with other
+applications at the tick call.  The application must ensure that
+exported data values are valid when \lstinline|tick| is called.  It
+must also expect that imported values may change and that event and
+message handlers are called.
+
+\begin{rationale}
+  The idea behind the \lstinline|tick| call is to hide the complexity
+  of data buffering and MPI transfer from the application.  For
+  efficient data transfer, MUSIC will try to buffer data both at the
+  sending and receiving port in order to send data in large chunks.
+  Internally, MUSIC will use a pre-computed schedule to keep track of
+  at what ticks the actual data transfer should take place and when
+  data should instead be buffered for later transfer.
+\end{rationale}
+
+
+\subsection{Simulation time}
+\index{simulation time}
+
+The method \lstinline|time| returns local time in seconds.
+
+\index{time}
+\begin{head}{time}
+  double Runtime::time ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & local time (s) \\
+\end{parameters}
+
+\lstinline|time| returns the local time.  Time starts at 0\,s and is
+incremented at every \lstinline|tick| call.  While it is possible, and
+recommended, to let MUSIC keep track of time for the application, this
+is not required.
+
+\begin{rationale}
+  To schedule data transfers, MUSIC needs to keep track of the
+  simulation time of all applications via its internal integer
+  representation.  If the application independently manages its own
+  clock, typically by incrementing a floating point variable, there is
+  a risk for drift between the two time representations.  The
+  \lstinline|time| function makes it possible for the application to
+  keep its clock in perfect synchronization with time in the other
+  applications.
+\end{rationale}
+
+
+\subsection{Finalization}
+
+An application supporting MUSIC should replace its call to
+\lstinline|MPI::Finalize| with a call to \lstinline|MUSIC::finalize|.
+
+\index{finalize}
+\begin{head}{finalize}
+  void Runtime::finalize ()
+\end{head}
+\begin{parameters}
+\end{parameters}
+
+\lstinline|MUSIC::finalize| makes sure all internally buffered data is
+sent and finally calls \lstinline|MPI::Finalize|.  Note that this
+means that communication via MPI will not be possible afterwards.
+
+
+\chapter{Adapting Existing Applications}
+
+In this chapter we will highlight the steps necessary to adapt an
+existing neural simulator to MUSIC.  We will assume that the simulator
+is already using MPI to simulate large networks of interconnected
+neurons.
+
+The two main tasks that need to be handled are: firstly, to create and
+map ports for data to be imported and exported, and, secondly, to
+ensure that the \lstinline|tick| function is called at regular
+intervals.
+
+
+\section{Creating and Mapping Ports}
+
+The application needs to inform MUSIC about what data to import and
+export, and where this data resides.  A simulator will typically use
+some sort of script files where the user specifies the model and other
+aspects of the simulation.  If possible, it is desirable to extend the
+scripting language of the simulator so that the user can specify what
+model variables to communicate, and what names to use for ports.
+
+Assuming that we have introduced such constructs into the scripting
+language, we must decide on a suitable point in the initialization
+process where ports should be created and mapped.  Since continuous
+data is read from, or written to, application memory space, the
+program must have allocated its runtime data structures in order to
+perform the mapping.
+
+Communication of spikes will use event ports. Function calls are used
+to send and receive individual spike events.  Sending of spikes is
+relatively straightforward, since the only thing needed is to add a
+call to the method \lstinline|insertEvent| at the location where
+spikes are normally detected in the program.  Receiving spikes
+requires more administration, since the spikes can be received earlier
+than when they should reach their destination compartment.  It is
+therefore necessary to save incoming spikes in some sort of sorted
+buffer (typically a priority queue).
+
+\begin{figure}
+  \begin{center}
+    \begin{minipage}[t]{0.45\textwidth}
+      \includegraphics[width=\textwidth]{figures/remapping}
+      \caption[Processing of incoming data]{\label{fig:remapping1}
+        The sender application presents the data to the output port in
+        the same order as it is stored internally.  The receiving
+        application will see the transferred data in the same order
+        and will explicitly have to implement a proper reordering to
+        implement a typical synaptic projection.
+      }
+    \end{minipage}
+    \hfill
+    \begin{minipage}[t]{0.45\textwidth}
+      \includegraphics[width=\textwidth]{figures/remapping2}
+      \caption[Remapping of data within MUSIC]{\label{fig:remapping2}
+        If there is a one-to-one correspondence between sending and
+        receiving neurons, the receiving application can specify an
+        appropriate index map to instruct MUSIC to send the data
+        directly to the right destination.
+      }
+    \end{minipage}
+  \end{center}
+\end{figure}
+
+In addition, MUSIC will always present the spikes as they appear in
+the sending group of neurons.  In most situations, the receiving
+application will want to implement a remapping to the target
+compartments, as illustrated in figure~\ref{fig:remapping1}.  One spike
+may thus end up at multiple postsynaptic compartments, spread out over
+the processors of the receiving application.
+
+In some situations it may be desirable for the receiving application
+to avoid this remapping.  The application can then utilize the different
+forms of mappings available in MUSIC to create a general permutation
+so that MUSIC will send spikes directly to the processor where they
+should be handled.  This situation is illustrated in
+figure~\ref{fig:remapping2}
+
+
+\section{Advancing Simulation Time}
+
+The application must call the \lstinline|tick| function repeatedly
+throughout the simulation.  The application will have to ensure that
+these calls are made at regular intervals, as specified to the runtime
+constructor.  Note that this refers to \emph{simulated time}; there is
+no need to consider how much computation time (``wall clock time'') is
+used between tick calls.
+
+If the application makes use of variable time steps internally, it may
+be necessary to use some sort of checkpoints at fixed intervals where
+tick can be called.  It is not necessary to call tick at every
+integration time step, but the calls should not be too infrequent.
+
+The tick calls are the only times during runtime when MUSIC will use
+MPI.  MUSIC will then use its own communicators, not to interfere with
+the MPI operations of the application.  Still, we recommend that the
+application does not intersperse the tick calls with ongoing MPI
+operations.
+
+When sending continuous values the application must ensure that data
+arrays mapped for output are filled with values relevant for the time
+of the \emph{next} tick.  After the \lstinline|tick| call, data arrays
+mapped for input will be filled with imported data belonging to the
+same point in time.  Note that \lstinline|Runtime::time| is updated
+\emph{during} the \lstinline|tick| call to reflect the current
+simulation time.
+
+
+\section{Initialization and Finalization}
+
+\subsection{Initiate MUSIC}\index{initiate MUSIC}
+
+The idea here is to replace the call to \lstinline|MPI::Init| with a
+call to the \lstinline|MUSIC:Setup| constructor.  The Setup
+constructor calls \lstinline|MPI::Init| for the application.
+
+The application will have to replace all uses of the global
+communicator \lstinline|MPI::COMM_WORLD| with the communicator
+supplied by MUSIC.  The global communicator will be global over all
+applications and it is necessary to limit the MPI operations to the
+group of MPI processes belonging to the application.
+
+There should be no need to link an application differently when it is
+used together with other applications in a MUSIC setting compared to
+when it is used in a stand-alone setting.  In order to support
+``standard'' operation for the application,
+\lstinline|Setup::communicator ()|, therefore, will return
+\lstinline|MPI::COMM_WORLD| if the job is started directly with
+\lstinline|mpirun| instead of with the MUSIC launcher.
+
+
+
+\subsection{Initiate the runtime phase}
+
+Creating the runtime object will implicitly call the \lstinline|Setup|
+object destructor to ensure that the application will no longer be
+able to change the communication pattern.  At this stage, MUSIC can
+build the plan for communication between different processes.
+
+\subsection{Finalize MUSIC}\index{finalize}\index{terminate}
+
+The application should also replace its call to
+\lstinline|MPI::Finalize|, normally used to shut down communication,
+by a call to \lstinline|MUSIC::finalize|.  This will internally call
+\lstinline|MPI::Finalize| after having flushed all pending data from
+internal buffers.
+
+\bibliographystyle{unsrtnat}
+\bibliography{music-rfc}
+
+\appendix
+
+\chapter{A Complete Example}
+
+This chapter shows a minimal but still complete example.  It consists
+of two applications, \texttt{waveproducer} and \texttt{waveconsumer},
+and a configuration file used to launch and connect them.
+
+
+\section{Configuration File}
+\label{sec:conffile}
+
+The configuration file starts the waveproducer application on four
+processors and waveconsumer on three.
+
+\lstinputlisting[language=Clean,frame=single]{wavetest.music}
+
+
+\section{Data Generating Application}
+
+\lstinputlisting{waveproducer.cc}
+
+
+\section{Data Consuming Application}
+
+\lstinputlisting{waveconsumer.cc}
+
+
+\chapter{C Interface}
+\label{app:cint}
+
+Most elements of the C interface can be constructed from their C++
+counterparts using a few translation rules:
+
+\begin{enumerate}
+\item All identifiers have the prefix \lstinline|MUSIC_|.
+\item Constructors translate to \lstinline|create| followed by the
+  class name.
+\item Destructors translate to \lstinline|destroy| followed by the
+  class name.
+\item Methods translate to class name followed by method name.
+\item References translate to pointers.
+\item Strings translate to \lstinline|char *|.
+\item Optional C++ arguments are required in C.
+\end{enumerate}
+
+Entries which do not strictly follow these rules are preceded with an
+extra comment in the following listing.
+
+\lstinputlisting{music-c-int.h}
+
+\chapter{Specification File Syntax}
+\label{sec:specsyntax}
+
+\newcommand{\nt}[1]{$<$#1$>$}
+
+\begin{tabular}{lcl}
+\nt{simulation spec}   & ::= & \{ \nt{application block} \} \\
+\nt{application block} & ::= & \nt{newline} '[' \nt{application id} ']' \{ \nt{declaration}
+\} \\
+\nt{application id}    & ::= & \nt{symbol} \\
+\nt{declaration}       & ::= & \nt{variable def} $|$ \nt{connection} \\
+\nt{variable def}      & ::= & \nt{variable} '=' \nt{value} \\
+\nt{variable}	       & ::= & \nt{symbol} \\
+\nt{value} 	       & ::= & \nt{integer} $|$ \nt{float} $|$ \nt{string} \\
+\nt{connection}	       & ::= & \nt{port id} \nt{direction} \nt{port id} [ \nt{width} ] \\
+\nt{port id}	       & ::= & \nt{application id} '.' \nt{port} $|$
+\nt{port} \\
+\nt{port}	       & ::= & \nt{symbol} \\
+\nt{direction}	       & ::= & $->$ $|$ $<-$ \\
+\nt{width}	       & ::= & '[' \nt{integer} ']' \\
+\end{tabular}
+
+\printindex
+
+\end{document}
+
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: t
+%%% eval: (flyspell-mode 1)
+%%% eval: (ispell-change-dictionary "american")
+%%% eval: (flyspell-buffer)
+%%% End: 
diff --git a/doc/music-rfc.bib b/doc/music-rfc.bib
new file mode 100644
index 0000000..cf5e93f
--- /dev/null
+++ b/doc/music-rfc.bib
@@ -0,0 +1,15 @@
+@Misc{mpi1.1,
+  author =	 {Message Passing Interface Forum},
+  title =	 {{MPI}: A Message-Passing Interface Standard},
+  month =	 {November},
+  year =	 2003,
+  howpublished = {{\url{http://www.mpi-forum.org/docs/mpi-11-html/mpi-report.html}}}
+}
+
+@Misc{mpi2.0,
+  author =	 {Message Passing Interface Forum},
+  title =	 {{MPI}-2: Extensions to the Message-Passing Interface},
+  month =	 {November},
+  year =	 2003,
+  howpublished = {{\url{http://www.mpi-forum.org/docs/mpi-20-html/mpi2\-report.html}}}
+}
diff --git a/doc/music-rfc.tex b/doc/music-rfc.tex
new file mode 100644
index 0000000..02c062d
--- /dev/null
+++ b/doc/music-rfc.tex
@@ -0,0 +1,1708 @@
+\documentclass[a4paper,twoside]{report}
+
+\usepackage[numbers]{natbib}
+\citestyle{newapa}
+\usepackage[utf8]{inputenc}
+\usepackage{fancyhdr}
+\usepackage{color}
+\usepackage{graphicx}
+\usepackage{listings}
+\usepackage{makeidx}
+\usepackage{comment}
+
+%%%%% Formatting %%%%%
+
+% Use the metatext environment around text that should not appear in
+% the final document
+%\newenvironment{metatext}%
+%{\color{blue}}%
+%{}
+\excludecomment{metatext}
+
+% Use the rationale environment around arguments for design decisions
+\newenvironment{rationale}%
+{\par\begin{quote}\textbf{Rationale:}}%
+{\par\end{quote}}
+
+
+% Use the head environment around method heads
+\lstnewenvironment{head}[1]%
+{\lstset{frame=topline,emph={#1},emphstyle=\color{blue}\textbf}}%
+{}
+
+
+% Use the parameters environment after heads
+\newenvironment{parameters}%
+{\begin{tabular}{@{\hspace{2em}}lp{0.6\textwidth}}}%
+{\end{tabular}\par\vspace{1mm}\par\hrule\par\vspace{5mm}}
+
+
+% Use the code environment around method code examples
+\lstnewenvironment{code}[1]%
+{\lstset{frame=single,caption={#1}}}%
+{}
+
+\renewcommand{\lstlistingname}{Example}
+
+% Use the responsible command to indicate which author is responsible
+% for the present section
+\newcommand{\responsible}[1]%
+{{\color{red}[#1 is responsible for this section]}}
+
+
+\fancyhead{}
+\fancyhead[L]{\slshape\leftmark}
+
+\pagestyle{fancy}
+\makeindex
+
+%%%%% Actual content starts here %%%%%
+\begin{document}
+
+\lstset{language=C++,identifierstyle=\ttfamily}
+
+\title{MUSIC --- Multi-Simulation Coordinator\\[2ex]
+  Request For Comments\\}
+
+\author{Örjan Ekeberg and Mikael Djurfeldt}
+
+\maketitle
+
+\begin{abstract}
+  MUSIC is an API allowing large scale neuron simulators using MPI
+  internally to exchange data during runtime.  MUSIC provides
+  mechanisms to transfer massive amounts of event information and
+  continuous values from one parallel application to another.  Special
+  care has been taken to ensure that existing simulators can be
+  adapted to MUSIC.  In particular, MUSIC handles data transfer
+  between applications that use different time steps and different
+  data allocation strategies.
+\end{abstract}
+
+
+\tableofcontents
+
+\listoffigures
+
+\chapter{Introduction}
+
+This document constitutes a preliminary specification for the
+multi-simulation coordinator MUSIC.  The main purpose of the current
+document is to make it possible for potential users of MUSIC to
+comment on the design before the full implementation is finalized.
+
+\section{Scope}
+
+MUSIC is a standard for run-time exchange of data between parallel
+applications in a cluster environment.  The standard is designed
+specifically for interconnecting large scale neuronal network
+simulators, either with each-other or with other tools.
+
+A typical usage example is illustrated in figure~\ref{fig:multisim},
+where three applications ($A$, $B$, and $C$) are executing in parallel
+while exchanging data via MUSIC.  We will refer to this as a
+\emph{multi-simulation}, since the participating applications
+typically are neuronal simulators, or tools to support such
+simulators.  In this example, application $A$ produces runtime data
+which is then used by $B$ and $C$.  In addition, $B$ and $C$ mutually
+send data to each other.  The data sent between applications can be
+either event based, such as neuronal spikes, or graded continuous
+values, for example membrane voltages.
+
+\begin{figure}
+  \begin{center}
+    \includegraphics[width=0.5\textwidth]{figures/multisim}
+    \caption[Typical multi-simulation]{\label{fig:multisim}
+      Illustration of a typical multi-simulation using MUSIC.  Three
+      applications, $A$, $B$, and $C$, are exchanging data during
+      runtime.
+    }
+  \end{center}
+\end{figure}
+
+The primary objective of MUSIC is to support multi-simulations where
+each participating application itself is a parallel simulator with the
+capacity to produce and/or consume massive amounts of data.  This
+promotes \emph{inter-operability} by allowing models written for
+different simulators to be simulated together in a larger system.  It
+also enables \emph{re-usability} of models or tools by providing a
+standard interface.  The fact that data is spread out over a number of
+processors makes it non-trivial to coordinate the transfer of data so
+that it reaches the right destination at the right time.  The task for
+MUSIC is to relieve the applications from handling this complexity.
+
+
+\section{Design Goals}
+
+\subsection{Portability}
+
+The MUSIC library and utilities have been designed to run
+smoothly on state-of-the-art high-performance hardware.  For maximal
+portability, the software is written in C++, which is the de facto
+standard for current high-end hardware.  MUSIC also provides a
+C-interface, making it possible for applications written in C or
+FORTRAN to participate in a MUSIC multi-simulation.
+
+Most, if not all, current efforts in large scale neuronal simulations
+are based on the MPI\index{MPI} standard.  MUSIC is built on top of
+MPI, and uses it to run the different simulators.  MUSIC provides
+means to allow each simulator to use MPI internally without
+interfering with the others.
+
+MUSIC has been developed using two reference platforms: Intel-based
+multi-core workstations and the IBM
+BlueGene/L\index{BlueGene/L}\index{IBM BlueGene} supercomputer.  These
+platforms can be considered as two extremes, where the multi-core
+machine represents a small parallel environment while the BlueGene/L
+represents a large scale massively parallel supercomputer with special
+requirements.  In particular, the compute nodes on the BlueGene/L do
+not support multiple threads or processes.
+
+
+\subsection{Simplicity}
+\label{sec:simplicity}
+
+For MUSIC to be useful, it must be possible to adapt existing
+simulators so that they can participate in a multi-simulation without
+too much effort.  We rely on the simulator developers to make these
+adaptations.  An important design goal has therefore been to adapt the
+design to the typical structure of current simulators.  It should be
+possible to add MUSIC library support without invasive restructuring
+of the existing code.
+
+The primary requirements on an application using MUSIC is that it
+declares what data should be exported and imported and that it
+repeatedly calls a function at regular intervals during the simulation
+to allow MUSIC to make the actual data transfer.
+
+
+\subsection{Independence}
+
+The MUSIC interface ensures that each individual application does not
+need special adaptation to specific properties of other applications.
+The application only needs to adhere to the specification of the MUSIC
+interface in order to communicate with other applications performing
+complementary tasks.  This makes the development of MUSIC-aware
+software independent of what other applications it will communicate
+with.
+
+We hope that this will facilitate the development of general purpose
+tools.  For example, a researcher can develop a tool for calculating
+synthetic EEG from simulation data.  Via MUSIC, this tool should then
+be useful for anybody using any neuronal simulator which supports the
+common MUSIC interface.
+
+
+\subsection{Performance}
+
+The MUSIC API has been designed to allow for data transport of high
+bandwidth and low latency within the cluster.  One means of ensuring
+the best use of the hardware while maintaining portability is to use
+the facilities of MPI for communication.  MPI encapsulates software
+optimizations for specific hardware. By basing the interface on MPI we
+can benefit from such optimizations.
+
+
+\subsection{Extensibility}
+
+Where possible, MUSIC allows for extensions by the application
+programmer.  Some classes in the MUSIC API (such as the index and data
+maps) can be subclassed in order to provide facilities not available
+directly in the API.
+
+
+\section{Terminology}
+
+\begin{description}
+\item[application] We use the term
+  \emph{application}\index{application} to denote a simulator or other
+  program interfaced to MUSIC.  Each application is a parallel
+  program, normally running on several processors.
+
+\item[multi-simulation] We use the term
+  \emph{multi-simulation}\index{multi-simulation} to refer to the
+  whole parallel execution of multiple applications coordinated by
+  MUSIC.
+
+\item[port] Each application declares its ability to produce and
+  consume data by publishing \emph{ports}\index{port}.  Ports are
+  named by the application and provided with information about the
+  datatype (continuous data, spike events, messages) and mapping onto
+  different processors.  Ports are either
+  \lstinline|input_ports|\index{input port} or
+  \lstinline|output_ports|\index{output port}.
+
+\item[connection] During the setup phase, MUSIC connects pairs of
+  ports together to form \emph{connections}\index{connection}.  During
+  the runtime phase, data is transferred over the connection from the
+  producer of the data to the consumer.  While an
+  \lstinline|input_port| can have only one connection, an
+  \lstinline|output_port| can be connected to multiple
+  \lstinline|input_ports|.
+\pagebreak
+\item[data map] A data map\index{data map} denotes the information on
+  where data actually resides within the application.  This is
+  typically stored internally in the port data structure.  Data to be
+  transferred over a connection can be regarded as a large array
+  distributed over multiple processors. The data map tells on
+  what processor each data element resides and how it should be
+  accessed.
+
+\item[ticks] During the runtime phase, all processes in each
+  application must make a \emph{tick}\index{tick} call at regular
+  intervals in simulated time.  At these tick points, MUSIC is allowed
+  to use MPI to transfer data between processors.
+\end{description}
+
+
+\section{Relation to Existing Software}
+
+MUSIC is not the only software project aiming to support
+inter-operability between neural simulators.  In this section we will
+briefly describe some related projects and specifically focus on how
+they relate to MUSIC.
+
+\paragraph{PyNN}\index{PyNN}
+
+PyNN is a Python package for simulator-independent specification of
+neuronal network models.  It provides a low-level procedural API and a
+high-level object-oriented API.  Neuronal network models which are
+specified using these API:s can be simulated on simulators supporting
+PyNN, such as Neuron\index{Neuron} and NEST\index{NEST}.
+
+PyNN could be extended to support multi-simulations using the MUSIC
+library.  Such an extension would provide means for controlling the
+interaction between the simulator and the MUSIC library and would, for
+example, support publishing of named ports.
+
+It is possible, in principle, to write Python code to directly handle
+communication between applications in a cluster, but such a solution
+would be inefficient compared to using MUSIC, and might, in the end,
+have to address the same problems which MUSIC provides a solution to.
+
+\paragraph{Neurospaces}\index{Neurospaces}
+
+The Neurospaces project promotes inter-operability and re-usability
+through the development of independent software components, some of
+which, together, will provide one of two alternative cores of the
+Genesis 3 simulator.  One of the components, the Neurospaces Model
+Container abstracts model description from the solver.  Another
+component, the Discrete Event System can handle distribution and
+queuing of spikes.  Components adhere to the CBI simulator
+architecture.
+
+It is possible to develop a MUSIC adapter consistent with the CBI
+simulator architecture.  This would allow the Neurospaces framework,
+and Genesis 3, to interface to independently running applications in a
+cluster environment.
+
+\begin{metatext}
+\paragraph{Neosim}\index{Neosim}
+
+\paragraph{MOOSE}\index{MOOSE}
+\end{metatext}
+
+\chapter{Execution Model}
+
+\section{Phases of Execution}
+
+A multi-simulation, i.e. a set of interconnected parallel
+applications, is executed in three distinct phases:
+\begin{description}
+\item[\textbf{Launch}]\index{launch phase} is the phase where all the
+  applications are started on the processors.  During this phase,
+  MUSIC is responsible for distributing and launching the application
+  binaries on the set of MPI processes allocated to the MUSIC job.
+  Since MPI can be initialized first when the applications have been
+  launched, most of this work needs to be performed outside of MPI.
+  In particular, the tasks of accessing the command line argument of
+  the MUSIC launch utility and of determining the ranks of processes
+  before MPI initialization therefore has to be handled separately for
+  different MPI implementations.
+
+  Technically, the launch phase begins when \texttt{mpirun} launches
+  the MUSIC binary and ends when the setup object constructor
+  returns.  (See further description below.)
+
+\item[\textbf{Setup}]\index{setup phase} is the phase when all
+  applications can publish what ports they are prepared to handle
+  along with the time step they will use and where data will be
+  present (where in memory and/or on what processor).  During the
+  setup phase, applications can read configuration parameters
+  communicated via the common configuration file.  At the end of the
+  setup phase, MUSIC will establish all connections.
+
+  The setup phase begins when the setup object has been created and
+  ends when the runtime object constructor returns.
+
+\item[\textbf{Runtime}]\index{runtime phase} is the phase when
+  simulation data is actually transferred between applications.  Via
+  \texttt{tick} calls the simulated time of applications is
+  kept in order.
+
+  The runtime phase begins when the runtime object has been created
+  and ends when the runtime object is destroyed.
+\end{description}
+
+From the application programmers point of view, these phases are
+clearly separated through the use of two main components of the
+MUSIC interface: the \emph{setup} and the \emph{runtime} object.  The
+launch phase is not visible for the application since it handles the
+situation before the application starts.
+
+When the application initializes MUSIC at the beginning of execution
+it receives a specific \emph{setup object}.  This object gives access
+to the functionality relevant during the setup phase via its methods.
+When done with the setup, the application program makes the transition
+to the runtime phase by passing the setup object as an argument to the
+\emph{runtime object} constructor which destroys the setup object.
+The runtime object provides methods relevant during the runtime phase
+of execution.
+
+\section{Spatial Distribution of Data}
+\label{sec:spatialdist}
+
+Communication between applications is handled by ports.  Ports are
+named sources (output ports) or sinks (input ports) of data flows.
+The data to be communicated may be differently organized in process
+memory on the receiver side compared to the sender side.  The
+applications may run on different numbers of processes, and, the data
+may be differently distributed among the sender processes and the
+receiver processes, as is shown in Figure~\ref{fig:datamapping}.  How
+does MUSIC know which data to send where?
+
+In MUSIC, there are two views of the data to be communicated over a
+connection.  Data elements are enumerated differently according to
+these views.  MUSIC uses \emph{global indices}\index{global index} to
+enumerate the entire set of data to be sent over the connection while
+\emph{local indices}\index{local index} enumerate the subset of data
+which is stored in the memory of a particular MPI process.  Data does
+not need to be ordered in the same way according to the two views.
+For example, local data stored in an array may be associated with an
+arbitrary subset of global indices in an arbitrary order.
+
+The MUSIC library is informed about the relationship between global
+and local indices and how data is stored in memory during the setup
+phase.  Two abstractions are used to carry this information:
+
+The \lstinline|index_map| maps local indices to global indices.  That
+is, the \lstinline|index_map| tells which parts of a distributed data
+array are handled by the local process and how the data elements are
+locally ordered.
+
+The \lstinline|data_map| encapsulates how a port accesses its data.
+The \lstinline|data_map| contains an \lstinline|index_map|.  While an
+index map is a mapping between two kinds of indices, the data map also
+contains information about where in memory data resides, how it is
+structured, and, the type of the data elements.  The type is used for
+marshalling when running on a heterogeneous cluster.
+
+During setup every process of the application individually provides
+the port with a \lstinline|data_map| (or an \lstinline|index_map| in
+the case of event ports).
+
+\begin{figure}
+  \begin{center}
+    \includegraphics[width=0.7\textwidth]{figures/datamapping}
+    \caption[Mapping of data]{\label{fig:datamapping} Data transfer
+      over a connection from an application running in four processes
+      to an application running in three processes.  The light gray
+      areas in the sender and receiver represents the MUSIC port.
+      Dashed lines divide the application into distinct processes.  }
+  \end{center}
+\end{figure}
+
+\begin{rationale}
+  While connections are often used to handle the transfer of spikes
+  from one group of neurons to another, they should not be regarded as
+  an implementation of synaptic projections\index{projections}.
+  Connections will only handle a direct one-to-one transport from one
+  application to another.  Re-mapping to actual receiving neurons,
+  e.g. to implement an all-to-all projection, must be handled by one
+  of the applications.  Thus, it may be better to regard the ports as
+  \emph{proxy-objects}\index{proxy objects}, providing indirect access
+  to neurons simulated by the other application.
+\end{rationale}
+
+
+\section{Timing Considerations}
+\label{sec:timing}
+  
+Different applications may use different time steps and it is the
+responsibility of MUSIC to ensure that data is delivered at the
+appropriate time.  In order to minimize handshaking, both parts of a
+connection pair locally calculate when the actual data transfer over
+MPI takes place.  To ensure that these calculations produce
+predictable results, simulation time is internally represented using
+integers with a global micro-timestep\index{micro-timestep} common for
+all applications.
+
+Simulation time\index{simulation time} is local for each application
+and MUSIC does not enforce unnecessary synchronization between these
+local clocks.  Thus, an application producing data may be running
+ahead of another application which consumes the same data.  MUSIC
+internally builds a schedule which ensures that data arrives at the
+appropriate local time in the receiving application.  Scheduling
+becomes more complex when data is not only transferred in a
+feed-forward manner, i.e. when the connection graph contains loops.
+In this case MUSIC has to rely on the existence of sufficient delays
+in the simulated model, typically corresponding to axonal
+delays\index{axonal delay}.
+
+\begin{figure}
+  \begin{center}
+    \begin{minipage}{0.45\textwidth}
+      \includegraphics[width=\textwidth]{figures/ticklogic}
+      \caption[Timing of data transfer, slowdown]{\label{fig:timingshorter}
+        Transfer of data when sender has a shorter
+        tick interval than the receiver}
+    \end{minipage}
+    \hfill
+    \begin{minipage}{0.45\textwidth}
+      \includegraphics[width=\textwidth]{figures/ticklogic2}
+      \caption[Timing of data transfer, speedup]{\label{fig:timinglonger}
+        Transfer of data when sender has a longer
+        tick interval than the receiver}
+    \end{minipage}
+  \end{center}
+\end{figure}
+
+Figures~\ref{fig:timingshorter} and \ref{fig:timinglonger} illustrate
+how MUSIC handles time when transferring continuous data over a connection.
+In figure~\ref{fig:timingshorter}, the sender application uses a
+shorter interval between the tick calls than the receiver.  The sender
+side uses values sampled at the tick points to interpolate a value
+corresponding to the point in time when the receiver makes its tick
+call.
+
+The dark middle area (labelled ``MPI'') is where the actual data
+transfer takes place.  MUSIC makes use of the fact that the receiving
+application can run with its simulation clock set independently of the
+sender.  The arrows going ``backwards in time'' in this area reflect
+the fact that the receivers clock is lagging.  This makes it possible
+for data to arrive in time despite the fact that it was available
+later (e.g. at tick \(s_2\)) than when it was arriving (at \(r_1\)),
+when talking about simulated time.
+
+Figure~\ref{fig:timinglonger} illustrates what happens when the
+receiver of continuous data is calling tick faster then the sender.
+The sender will then buffer up values from the preceding and current
+ticks and transfer this at a suitable tick call.  The receiver will
+portion these values out by interpolating at the appropriate ticks.
+
+The strategy of having the receiver application running with a delayed
+local clock only works when the connection graph forms a directed
+acyclic graph (DAG)\index{DAG}\index{acyclic graph}\index{loops}.
+When loops occur it is necessary to allow for data arriving late, at
+least somewhere along each loop.  MUSIC handles this via
+\emph{acceptable latency}\index{acceptable latency}\index{latency}
+which is a property of event input ports.  The receiving application
+declares how late, according to simulation time, data may arrive, thus
+giving MUSIC room for resolving the scheduling problem.  In the case
+of continuous data, the application specifies a
+\emph{delay}\index{delay} which fulfills the same purpose.
+
+In figures \ref{fig:timingshorter} and \ref{fig:timinglonger}, the
+sending application must be running ahead of the receiver in order to
+maintain the illusion that communication is instantaneous.
+Figure~\ref{fig:timeline} illustrates the timing relation between
+sender and receiver along a real time axis (wallclock time) when the
+receiver accepts a delay of incoming data.  This allows the receiver
+(B) to run ahead of the sender (A), thus creating the slack necessary
+to make schedules for communication loops.
+
+\begin{figure}
+  \begin{center}
+    \includegraphics[width=0.7\textwidth]{figures/timeline}
+    \caption[Timing of ticks]{\label{fig:timeline}
+      This figure illustrates how MUSIC can allow one application (A)
+      to execute ahead of another (B) when transferring continuous
+      data.  The receiver (B) has specified a delay on the input port
+      which means that the value to be delivered at each tick (gray
+      areas) corresponds to a simulated time in A (blue arrows) which
+      has already happened.
+
+      Note that the tick times when MUSIC actually transfers data will
+      be aligned on the real time axis, since blocking communication
+      is used.  In practice, one of the applications will have to wait
+      for the other to reach the same point in its execution.
+    }
+  \end{center}
+\end{figure}
+
+
+\section{Message Ports}\index{message port}
+
+In addition to the port types which handle continuous and spike event
+data, MUSIC provides \emph{message ports}.  Message ports allow for
+transmission of arbitrary messages of, for example, control
+information between applications.  A multi-simulation may, for
+example, be controlled by a script running in a Python process on one
+of the cluster nodes.  The script may use a message port to alter a
+parameter or turn on a stimulus in an application at a certain point
+in time.
+
+\pagebreak
+Messages sent from any process on the sender side of the connection
+are routed to all processes on the receiver side which have announced
+there willingness to receive messages.  Contrary to ports for
+continuous data, any marshalling is the responsibility of the sender
+and receiver application.
+
+To achieve independence between MUSIC applications, it is recommended
+that messages are text strings with the syntax of the interpreter
+language of the receiving application, and that these text strings
+originate from a user-specified configuration file read by the sending
+application.
+
+
+\section{Application Responsibilities}
+
+One goal of MUSIC has been to limit the responsibilities imposed on
+each application (c.f. section \ref{sec:simplicity}).  Here we present
+a step-by-step list of what an application must do in order to
+participate in a multi-simulation.
+
+\begin{enumerate}
+\item \textbf{Initiate MUSIC}\index{initiate MUSIC}
+
+  This is done by calling the \lstinline!setup! function.
+\item \textbf{Create ports}
+
+  Data to be imported and exported is identified by creating named
+  ports.
+\item \textbf{Map ports}\index{map ports}
+
+  MUSIC is informed about where the actual data is located.  This
+  includes information about which processor owns each data element.
+  For continuous data it also includes information about where in
+  memory it is stored, while for event data it specifies how to
+  receive events.
+\item \textbf{Initiate the runtime phase}
+
+  At this stage, MUSIC can build the plan for communication between
+  different processes.
+\item \textbf{Advance simulation time}\index{tick}\index{advance time}
+  \index{time}
+
+  The application must call \lstinline!tick! at regular intervals
+  to give MUSIC the opportunity to transfer data.
+\item \textbf{Finalize MUSIC}\index{finalize}\index{terminate}
+
+  By deleting the runtime object, all MUSIC communication is terminated.
+\end{enumerate}
+
+
+\chapter{Starting a Multi-Simulation}
+
+\section{Overview}
+
+Parallel programs based on MPI are normally started by running a
+special program called \texttt{mpirun}\index{mpirun} (for MPI-1) or
+\texttt{mpiexec}\index{mpiexec} (for MPI-2).  To start multiple
+applications and enable them to communicate with each other, MUSIC
+utilizes a special launcher program called \texttt{music}\index{music
+  (launcher)} which, in turn, starts the different applications.
+Information about which applications should be started, and the
+communication pattern between them is described in a common
+\emph{configuration file}\index{configuration file}.
+
+\begin{rationale}
+  The reason for not controlling configuration via the MUSIC API is
+  that individual applications should remain ignorant about the
+  structure of the full multi-simulation.  Thus, the API provides
+  methods for asking about the parts of the configuration relevant for
+  that application, i.e. its ports, but does not expose the complete
+  communication graph.
+\end{rationale}
+
+
+\section{The Configuration File}
+
+The main purpose of the configuration file is to control what
+applications to start, and to connect output ports to input ports.
+The configuration file specifies the number of MPI processes allocated to
+each application.
+
+The configuration file consists of a sequence of blocks, each starting
+with a non-indented bracket:
+
+\begin{quote}
+  [\emph{application\_label}]
+\end{quote}
+
+\noindent Each block consists of a sequence of configuration variable
+definitions applying to one application.  The application label is
+used to refer to ports of the application.  A variable definition
+takes the form of an assignment:
+
+\begin{quote}
+  \emph{varname} = \emph{value}
+\end{quote}
+
+\pagebreak
+The following variable names have special meaning to MUSIC:
+\begin{description}
+  \item[binary] Pathname to application binary
+  \item[args] Command line given to the binary
+  \item[np] The number of MPI processes to allocate for the application
+  \item[timebase] The length of a MUSIC micro-step, that is, the
+    resolution of {MUSIC}:s internal clocks).  (Default value is 1
+    ns.)
+\end{description}
+\begin{rationale}
+  The possibility to specify the MUSIC timebase is provided since the
+  timebase is a compromise between resolution and maximal simulation
+  time.  With 64-bit clocks, a timebase of 1 ns gives a maximal
+  simulation time of 585 years which should be sufficient for most
+  applications.
+\end{rationale}
+
+Arbitrarily named parameters may also be included in the configuration
+file and these parameters can be accessed from the applications.
+
+A connection between an output and input port is specified using the
+following syntax:
+\begin{quote}
+  \emph{application\_label.port\_name} \lstinline|->| \emph{application\_label.port\_name}
+\end{quote}
+\noindent  The direction of the arrow (\lstinline|->|, \lstinline|<-|) indicates the
+direction of data transport.  An output port can be connected to
+multiple input ports while an input port can be connected to, at most,
+one output port.
+
+Optionally, the width of the connections between applications can be
+specified:
+\begin{quote}
+  \emph{application\_label.port\_name} \lstinline|->|
+  \emph{application\_label.port\_name} [\emph{width}]
+\end{quote}
+The application label can be omitted if it refers to the application
+being specified by the surrounding block.
+An example of a simple configuration file can be seen in
+section~\ref{sec:conffile}.  Appendix~\ref{sec:specsyntax} specifies
+the formal syntax of configuration files.
+
+\begin{rationale}
+  Information from the configuration file needs to be available both
+  in order to launch the application binaries and during the setup
+  phase.  Since launching must be done prior to MPI initialization, it
+  is not possible to distribute configuration information via MPI
+  itself.  In the reference implementation of MUSIC, environment
+  variables are used to distribute this information to the
+  applications.
+
+  This information transfer is hidden within MUSIC, so a different
+  implementation of MUSIC may use another technique.  In particular,
+  if the applications are launched from a scripting program, such as
+  PyNN\index{PyNN}, that program must also take care of transferring
+  the relevant configuration information to the applications.
+\end{rationale}
+
+
+\chapter{Application Program Interface}
+
+\section{Conventions}
+
+This chapter describes the API to the MUSIC library.  The API is
+object oriented and all communication with the library is performed
+via instance methods of different classes of objects.  Appendix
+\ref{app:cint} presents an alternative C interface.  The most common
+way of passing objects as arguments in MUSIC is via pointers.  The
+only exception is the setup constructor.  The convention regarding
+memory management is that the caller should make sure that objects
+exist in memory during the entire execution of the method, and is also
+responsible for the deallocation of objects afterwards.
+
+
+\section{Error handling}
+
+MUSIC attempts to fall back on the error handling mechanisms of MPI.
+A MUSIC exception thus results in a call to the MPI error handler.
+A particular implementation of the MUSIC library does not guarantee
+that it handles all kinds of errors that may occur during MUSIC calls.
+Each error handled by MUSIC generates an exception, and MUSIC installs
+suitable error codes, classes and strings so that the MPI error
+handler is able to generate suitable error messages.
+
+MUSIC follows the style of error handling in the MPI standard, which
+is described in sections 7.2 and 7.3 in the MPI 1.1
+report\cite{mpi1.1} and in section 2.8 of the MPI 2.0
+report\cite{mpi2.0}.  The default error handler of MPI is
+\lstinline|MPI_ERRORS_ARE_FATAL| which means that any error handled by
+MUSIC will result in the program being aborted.  Using the error
+handling of MPI requires features only described in the MPI 2.0
+report.  For MPI implementations which lack this support, MUSIC uses
+its own error handler which has the same behavior as
+\lstinline|MPI_ERRORS_ARE_FATAL|.
+
+\begin{rationale}
+  MUSIC adheres to the error handling strategy of MPI since the
+  application is already using MPI and should not need to implement a
+  second error handling strategy when converted to use MUSIC.
+\end{rationale}
+
+\section{Setup}
+
+\subsection{The setup constructor}
+
+Each application initializes the MUSIC library through a call to the
+setup constructor\index{setup}.  This constructor, in turn, calls
+\lstinline|MPI::Init|\index{MPI::Init}\index{init} to initialize
+MPI\index{initialize MPI}.  The setup constructor creates the setup
+object through which the application can retrieve configuration
+information, get an application wide communicator, and setup ports.
+
+\begin{head}{setup}
+  setup::setup (int& argc, char**& argv)
+\end{head}
+\begin{parameters}
+  \lstinline|argc| &%
+  reference to the \lstinline|argc| argument of \lstinline|main| \\
+  \lstinline|argv| &%
+  reference to the \lstinline|argv| argument of \lstinline|main| \\
+\end{parameters}
+
+This constructor must be called at most once; subsequent calls are
+erroneous.  It accepts the \lstinline|argc| and \lstinline|argv| that are
+provided by the arguments to \lstinline|main|.
+\index{argc}\index{argv}
+
+\begin{code}{Initializing MUSIC}
+int main (int argc, char *argv[])
+{
+  MUSIC::setup* setup = new MUSIC::setup (argc, argv);
+
+  /* parse arguments */
+  /* rest of program */
+}
+\end{code}
+
+\begin{rationale}
+  The idea behind creating a specific setup object is to ensure that
+  the application does not accidentally call functions relevant only
+  for the setup phase at other times.
+\end{rationale}
+
+
+\subsection{Communicators}
+
+During a multi-simulation the MUSIC library will create a unique
+intra-communi\-cator over the group of processes assigned to each
+application.  This application wide communicator takes the role of the
+global communicator \lstinline|MPI::COMM_WORLD| and is retrieved from
+the setup object through a call to the \lstinline|communicator|
+method.\index{communicator}
+
+\begin{head}{communicator}
+  MPI::Intracomm setup::communicator ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & the application wide communicator \\
+\end{parameters}
+
+The application is supposed to use the application wide communicator
+in place of
+\lstinline|MPI::COMM_WORLD|\index{MPI::COMM\_WORLD}\index{COMM\_WORLD}. If
+the application binary has been launched using \lstinline|mpirun|
+instead of the \lstinline|music| utility, \lstinline|communicator ()|
+will return \lstinline|MPI::COMM_WORLD| as the application wide
+communicator.
+
+\pagebreak
+\index{rank}\index{Get\_rank}
+\begin{code}{Accessing the application-wide communicator}
+/* communicator with global scope */
+extern MPI_Comm comm;
+
+...
+{
+  ...
+  comm = setup->communicator ();
+  int rank = comm.Get_rank ();
+  ...
+}
+\end{code}
+
+\begin{rationale}
+  An alternative to provide the \lstinline|communicator| function
+  would have been to redefine \lstinline|MPI::COMM_WORLD|.  This would
+  ensure that an application does not accidentally use the global
+  communicator.  However, it may not always be possible to dynamically
+  redefine this variable in all MPI implementations, so for the sake
+  of portability, we have chosen a more straightforward technique.
+\end{rationale}
+
+
+\subsection{Port creation}
+
+Ports\index{ports} are named sources (output ports) or sinks (input
+ports) of data flows.  Output and input ports are distinct classes.
+Ports are further subdivided into distinct classes depending on
+whether they handle continuous data, event data or messages.
+
+\index{publish\_output}\index{publish\_input}
+\begin{head}{publish_cont_output,publish_cont_input,
+            ,publish_event_output,publish_event_input,
+            ,publish_message_output,publish_message_input}
+  cont_output_port*
+  setup::publish_cont_output (string id)
+
+  cont_input_port*
+  setup::publish_cont_input (string id)
+
+  event_output_port*
+  setup::publish_event_output (string id)
+
+  event_input_port*
+  setup::publish_event_input (string id)
+
+  message_output_port*
+  setup::publish_message_output (string id)
+
+  message_input_port*
+  setup::publish_message_input (string id)
+\end{head}
+\begin{parameters}
+  \lstinline|id| & port name \\
+  \emph{return value} & an unmapped port \\
+\end{parameters}
+
+\pagebreak
+Ports have two stages in life: the \emph{unmapped} stage and the
+\emph{mapped} stage.  A port is unmapped when created.  The MUSIC
+configuration file specifies connections between ports.  It is
+possible to ask an unmapped port if it is connected, if it has a width
+specified and, if so, what width it has.  A port becomes mapped when
+its method \lstinline|map| is called.
+
+\begin{code}{Creating an unmapped port}
+cont_output_port* out =
+   setup->publish_cont_output ("out");
+\end{code}
+
+\subsection{General port methods}
+
+The port API includes methods to ask a port if it is connected, if it
+has a width specified, and, if so, what that width is.
+
+\subsubsection{Port connectivity}
+
+The method \lstinline|is_connected| is used to check if the user has
+specified a connection of this port to another port in the
+configuration file.
+
+\index{is\_connected}\index{connected port}
+\begin{head}{is_connected}
+  bool port::is_connected ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & \lstinline|true| only if connected\\
+\end{parameters}
+
+This method is typically used in cases where the use of some of the
+ports of the application is optional.  In such a case, it is not
+sensible to allocate any application resources to support the data
+flow in question.  One example is if one wants to support output of
+membrane potentials from a certain population of cells, but don't want
+to waste resources if no one is listening.
+
+\begin{code}{Optional handling of ports}
+cont_output_port* out =
+   setup->publish_cont_output ("Vm");
+/* map port only if anyone is listening */
+if (out->is_connected ())
+  /* allocate application resources and map port */
+\end{code}
+
+\subsubsection{Port width}
+\label{sec:width}
+
+The width of a port\index{port width}, that is the number of data
+elements transferred in parallel from a cont port or the largest
+possible id of an event port $+$ 1, can be specified in the
+configuration file.  This should be thought of as a request for a
+given width.  Applications can use the method \lstinline|has_width| to
+determine if a width has been specified and retrieve it using
+\lstinline|width|.  Message ports do not have width.
+
+\pagebreak
+\index{has\_width}
+\begin{head}{has_width}
+  bool port::has_width ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & \lstinline|true| only if port width has been
+                         specified \\
+\end{parameters}
+
+\index{width}
+\begin{head}{width}
+  int port::width ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & port width \\
+\end{parameters}
+
+\begin{rationale}
+  Applications can use the above methods to adapt their port width.  A
+  typical usage would be a general purpose post-processing tool which
+  receives information from an ongoing simulation.  Such a tool can
+  publish a number of optional input ports and then use
+  \lstinline|is_connected| and \lstinline|width| to adapt its internal
+  processing depending on what kind of data source it is actually
+  connected to.  See example \ref{code:adaptivewidth}.
+\end{rationale}
+
+
+\begin{code}{Publishing port of adaptive width\label{code:adaptivewidth}}
+{
+  ...
+  /* Publishing a port of adaptive width */
+  double* state_vars;
+  MUSIC::cont_input_port* in =
+     setup->publish_cont_input ("in");
+  if (!in->has_width ())
+    /* report error */
+  else
+    {
+      int size = in->width ();
+      /* for clarity we assume that n_elements
+         is a multiple of size */
+      int n_local = n_elements / size;
+      /* example continues as in next example */
+      ...
+      
+    }
+}
+\end{code}
+
+
+\subsection{Mapping cont ports}
+\index{cont ports}
+
+A port is informed about what data exists locally and how to access it
+by mapping it.  Cont ports transfer data from or to memory during
+\lstinline|tick| calls and need to know the layout of data in memory.
+In addition, the marshalling (conversion between different bit level
+representations) performed on heterogeneous clusters requires
+information about the data type being transferred.  This information
+is captured by the data map argument \lstinline|dmap|.  The
+\lstinline|data_map| type is described in section \ref{sec:datamap}
+below.
+
+\index{map}\index{mapping cont ports}
+\begin{head}{map}
+  void cont_output_port::map (data_map* dmap,
+                              int max_buffered)
+
+  void cont_input_port::map (data_map* dmap,
+                             double delay,
+                             int max_buffered,
+                             bool interpolate)
+\end{head}
+\begin{parameters}
+  \lstinline|dmap| & the data map associated with the port \\
+  \lstinline|delay| & delay of data arrival in simulation time (s) \\
+  \lstinline|max_buffered| & maximal amount of data buffered (ticks)
+  \\
+  \lstinline|interpolate| & enable interpolation (boolean) \\
+\end{parameters}
+
+The optional argument \lstinline|delay| informs MUSIC of when,
+according to simulation time, to sample data on the sender side.  If
+enabled, linear interpolation is used to obtain an approximation of
+the state at this time.  The default delay is zero.  Delayed continuous
+data may be used in connectionist networks when modeling brain
+pathways.  A delay is \emph{required} at some point when communicating
+continuous data in a loop (c.f. section \ref{sec:timing}).
+
+Buffering data in output and input ports gives more efficient
+communication since data can be sent fewer times in larger packets.
+By default MUSIC buffers some reasonable amount of data.  In certain
+situations it is necessary to be careful about memory usage.  Using
+the optional argument \lstinline|max_buffered| the application can
+give MUSIC a bound on how much data to buffer.  MUSIC decides how much
+data to buffer based on the lowest \lstinline|max_buffered| parameter
+given when mapping each of a set of connected ports and on latency
+considerations when applications are connected in loops.  A
+\lstinline|max_buffered| value of \(N\) ticks means: don't buffer more
+data than is sufficient for communicating at every \(N\)\,th tick.
+
+When the optional argument \lstinline|interpolate| is
+\lstinline|true|, MUSIC uses linear interpolation to determine the
+values delivered on the receiver side.  This is the default behavior.
+By passing \lstinline|false| this interpolation can be switched off in
+which case MUSIC selects the sample on the sender side which is
+closest according to simulation time.
+
+
+\clearpage
+\begin{code}{Mapping ports to internal data\label{code:mapping}}
+{
+  ...
+  int size = comm.Get_size ();
+  int rank = comm.Get_rank ();
+  /* for clarity we assume that n_elements
+     is a multiple of size */
+  int n_local = n_elements / size;
+  double* state_vars = new double[n_local];
+  MUSIC::cont_input_port* out =
+     setup->publish_cont_output ("out");
+  MUSIC::array_data dmap (state_vars, MPI::DOUBLE,
+                          rank * n_local, n_local);
+  out->map (&dmap);
+  ...
+}
+\end{code}
+
+
+\subsection{Mapping event ports}
+\index{event ports}
+
+\index{map}\index{mapping event ports}
+\begin{head}{map}
+  void event_output_port::map (index_map* indices,
+                               int max_buffered)
+
+  void event_input_port::map (index_map* indices,
+                              event_handler* handle_event,
+                              double acc_latency,
+                              int max_buffered)
+\end{head}
+\begin{parameters}
+  \lstinline|indices| & the index map associated with the port \\
+  \lstinline|handle_event| & a user-defined event handler \\
+  \lstinline|acc_latency| & acceptable latency for incoming data (s) \\
+  \lstinline|max_buffered| & maximal amount of data buffered (ticks) \\
+\end{parameters}
+
+Since event ports don't access data the same way as cont ports, they
+do not require a full \lstinline|data_map|.  Events are communicated
+to the application through an \emph{event handler}\index{event
+handler}.  The event handler is called by MUSIC when the application
+calls \lstinline|tick|.  It is called once for every spike delivered.
+
+Some spiking neural network models include axonal delays.  The MUSIC
+framework assumes that handling and delivery of delayed spikes occurs
+on the receiver side.  In such a case, the receiver may allow MUSIC to
+deliver a spike event later than its time stamp according to local
+time.  The maximal acceptable latency is specified through the
+\lstinline|acc_latency|\index{acc\_latency} argument.
+
+The optional argument \lstinline|max_buffered|\index{max\_buffered}
+has a similar meaning as for cont ports above but the actual amount
+of data buffered is, in this case, not deterministic since it is
+dependent on spike rate.
+
+\pagebreak
+\subsubsection{Sending events}
+\index{sending events}
+
+The sender registers events for transmission by calling the method
+\lstinline|insert_event|.
+
+\index{insert\_event}
+\begin{head}{insert_event}
+  void event_output_port::insert_event (double t, int id)
+\end{head}
+\begin{parameters}
+  \lstinline|t| & trigger time of the event (s) \\
+  \lstinline|id| & the sender local index \\
+\end{parameters}
+
+MUSIC guarantees that this event will be delivered through a call to
+the user-specified \lstinline|event_handler| on the receiver side no
+later that the acceptable latency relative to receiver local time.
+The time \lstinline|t| must be between the simulation time of the last
+tick and that of the next.
+
+
+\subsubsection{Receiving events}
+\index{receiving events}
+
+\index{event\_handler}
+\begin{head}{event_handler,operator}
+  class event_handler {
+  public:
+    virtual void operator () (double t, int id) = 0;
+  };
+\end{head}
+\begin{parameters}
+  \lstinline|t| & trigger time of the event (s) \\
+  \lstinline|id| & the receiver local index \\
+\end{parameters}
+
+Event handlers are called by event input ports to deliver events.  The
+application is supposed to customize \lstinline|event_handler| by
+subclassing it.
+
+
+\subsection{Mapping message ports}
+\index{message ports}
+
+Message ports behave similarly to event ports in that messages are
+sent and delivered using similar mechanisms, but while events are
+routed between processes based on event id, messages are routed to all
+processes on the receiver side which have provided a
+\lstinline|message_handler| to \lstinline|map|.  All arguments to
+\lstinline|map| for message ports are optional.
+
+\index{map}\index{mapping message ports}
+\begin{head}{map}
+  void message_output_port::map (int max_buffered)
+
+  void message_input_port::map (message_handler* handler,
+                                double acc_latency,
+                                int max_buffered)
+\end{head}
+\begin{parameters}
+  \lstinline|handler| & a user-defined message handler \\
+  \lstinline|accept_latency| & acceptable latency for incoming data (s) \\
+  \lstinline|max_buffered| & maximal amount of data buffered (ticks) \\
+\end{parameters}
+
+
+\pagebreak
+\subsubsection{Sending messages}
+\index{sending messages}
+
+The sender registers a message for transmission by calling the method\\
+\lstinline|insert_message|.
+
+\index{insert\_message}
+\begin{head}{insert_message}
+  void message_output_port::insert_message (double t,
+                                            void* msg,
+                                            size_t size)
+\end{head}
+\begin{parameters}
+  \lstinline|t| & time stamp (s) \\
+  \lstinline|msg| & pointer to message \\
+  \lstinline|size| & size of message in bytes \\
+\end{parameters}
+
+MUSIC will deliver this message through a call to the user-specified \\
+\lstinline|message_handler| on the receiver side no later than
+\lstinline|acc_latency| with regard to the time stamp.
+
+\begin{code}{Sending a message}
+{
+  ...
+  char m[] = "string to send";
+  port->insert_message (runtime->time (), m, sizeof (m));
+  ...
+}
+\end{code}
+
+
+\subsubsection{Receiving messages}
+\index{receiving messages}
+
+\begin{head}{message_handler,operator}
+  class message_handler {
+  public:
+    virtual void operator () (double t,
+                              void* msg,
+                              size_t size) = 0;
+  };
+\end{head}
+\begin{parameters}
+  \lstinline|t| & time stamp supplied by sender (s) \\
+  \lstinline|msg| & pointer to message subclass instance \\
+  \lstinline|size| & size of message instance in bytes \\
+\end{parameters}
+
+Message handlers are called by message input ports to deliver
+messages.  The application is supposed to customize
+\lstinline|message_handler| by subclassing.  It is recommended that
+messages are text strings with the syntax of the interpreter language
+of the receiving application, and that these text strings originate
+from a user-specified configuration file read by the sending
+application.
+
+The message given to the \lstinline|message_handler| is deallocated by
+the MUSIC library.
+
+
+\subsection{Index maps}
+\index{index maps}
+
+An \lstinline|index_map| is a mapping from local data element indices to
+global. An index map instance thus holds information of which global
+indices belong to the local MPI process and of their order with regard
+to local index.  MUSIC implements two subclasses of
+\lstinline|index_map|: \lstinline|permutation_index| and
+\lstinline|linear_index|.  The most general form is
+\lstinline|permutation_index| which allows for an arbitrary mapping.
+
+\index{permutation\_index}
+\begin{head}{permutation_index}
+  permutation_index::permutation_index (int* indices,
+                                        int size)
+\end{head}
+\begin{parameters}
+  \lstinline|indices| & vector of global indices \\
+  \lstinline|size| & number of global indices \\
+\end{parameters}
+
+\index{linear\_index}
+\begin{head}{linear_index}
+  linear_index::linear_index (int baseindex, int size)
+\end{head}
+\begin{parameters}
+  \lstinline|baseindex| & global index of first local element \\
+  \lstinline|size| & number of contiguous global indices \\
+\end{parameters}
+
+When a cont output port is mapped it becomes associated with a set of
+state variables (or other data) in the memory of the sender.  When the
+receiver calls \lstinline|runtime::tick|, an estimate of the values
+of these variables are stored in a set of variables associated with an
+input port on the receiver side.  Similarly, an event output port is
+mapped to a set of event id:s.
+
+While the number of variables or id:s on the receiver side is always
+the same as on the sender side, the data can be distributed in
+different ways between MPI processes on the sender side compared to
+the receiver side.  In fact, sender and receiver may consist of
+different numbers of processes.
+
+Index maps are used in each MPI process to tell MUSIC how data is
+distributed and ordered by enumerating the global indices represented
+by the process in local order.
+
+\subsection{Data maps}
+\label{sec:datamap}
+\index{data maps}
+
+A \lstinline|data_map| encapsulates how a port accesses its data.
+While an index map is a mapping between two kinds of indices, the data
+map also contains information about where in memory data resides, how
+it is structured, and, the type of the data elements.
+\lstinline|array_data| is a subclass of \lstinline|data_map| which
+describes arrays of data elements.  See example \ref{code:mapping}.
+
+\index{array\_data}
+\begin{head}{array_data}
+  array_data::array_data (void* buffer, MPI_Datatype type,
+                          index_map* map)
+\end{head}
+\begin{parameters}
+  \lstinline|buffer| & data memory location \\
+  \lstinline|type|   & data type \\
+  \lstinline|map|    & index map \\
+\end{parameters}
+
+Since data organized in arrays is common, MUSIC provides a convenience
+form of the array data map constructor which also creates a linear
+index map:
+
+\pagebreak
+\begin{head}{array_data}
+  array_data::array_data (void* buffer,
+                          MPI_Datatype type,
+                          int  baseindex,
+                          int size)
+\end{head}
+\begin{parameters}
+  \lstinline|buffer|    & data memory location \\
+  \lstinline|type|	& data type \\
+  \lstinline|baseindex| & global index of first local element \\
+  \lstinline|size|      & number of contiguous global indices \\
+\end{parameters}
+
+
+\subsection{Configuration variables}
+\index{configuration variables}
+
+The values of all variables defined in the configuration file can be
+queried using the method \lstinline|config|.
+
+\index{config}
+\begin{head}{config}
+  bool setup::config (string name, string* result)
+
+  bool setup::config (string name, int* result)
+
+  bool setup::config (string name, double* result)
+\end{head}
+\begin{parameters}
+  \lstinline|name|     & variable name \\
+  \lstinline|result|  & pointer to location where result should go \\
+  \emph{return value} & true if value of correct type was found \\
+\end{parameters}
+
+Querying for a value of type \lstinline|int| or \lstinline|double|
+expects a value of the correct type, if defined in the configuration
+file.  If the variable is defined, but its value can't be translated
+into the correct type this causes an error condition.
+
+\begin{code}{Querying configuration variables}
+/* Retrieving the parameter gKCa
+   from configuration file */
+double gKCa;
+if (!config ("gKCa", &gKCa))
+  gKCa = 29.5e-9; // default value
+\end{code}
+
+\section{Runtime}
+
+\subsection{The runtime constructor}
+
+\begin{head}{runtime}
+  runtime::runtime (setup* s, double h)
+\end{head}
+\begin{parameters}
+  \lstinline|s| & pointer to the setup object \\
+  \lstinline|h| & simulated time elapsed between each tick (s) \\
+\end{parameters}
+
+Creation of the runtime object marks the transition from the setup to
+the runtime phase.  The runtime object constructor destroys the setup
+object, effectively making it impossible to create new ports.  All
+data structures which have been associated with ports during mapping
+must be initialized to some suitable start value at the time of the
+call to the runtime constructor.  These values are used during early
+data transfers of data sampled at negative values of simulation time
+and, thus, not available.
+
+\begin{code}{runtime}
+...
+MUSIC::runtime runtime = MUSIC::runtime (setup, stepsize);
+...
+\end{code}
+
+\begin{rationale}
+  The step size is given as a real number (in seconds) since this
+  makes most sense from the applications point of view.  Internally,
+  this number is converted to an integer (using the time micro step
+  time base).  This is made to ensure that all processes use exactly
+  the same numbers even when the multi-simulation is running on mixed
+  architectures.  Both sides of a connection must agree on when data
+  is transferred over the MPI connector to minimize the
+  need for handshaking during the runtime phase.
+\end{rationale}
+
+\begin{rationale}
+  In order to create a deterministic schedule for buffering and data
+  transfer, we require that \lstinline|tick| is called at fixed
+  intervals in simulated time.  We realize that some applications may
+  use a variable time step\index{variable time step} for their
+  numerical integrations, which may then make it harder to execute
+  these tick calls at the right time.  However, allowing variable tick
+  steps would have made it impossible to use a pre-computed
+  deterministic schedule and enforced repeated handshaking throughout
+  the runtime phase, resulting in a substantial performance
+  degradation.
+
+  Note that the tick step does not need to be equal to the internally
+  used integration step\index{integration step}.  We believe that most
+  large scale parallel simulators already have some means for fixed
+  interval operations, e.g. to handle logging to files or graphics,
+  which may be utilized also for the tick calls.
+\end{rationale}
+
+
+\subsection{The tick}
+\index{tick}
+
+\begin{head}{tick}
+  void runtime::tick ()
+\end{head}
+\begin{parameters}
+\end{parameters}
+
+The tick function must be called at regular intervals in simulation
+time.  The application chooses the interval as a parameter to the
+\lstinline|runtime| constructor, normally based on the time step used
+in the application.  The \lstinline|tick| function is typically called
+in the main simulation loop of each application.  Different
+applications may use different tick-intervals and MUSIC will ensure
+that time is incremented consistently throughout the multi-simulation.
+
+The MUSIC library may, or may not, exchange data with other
+applications at the tick call.  The application must ensure that
+exported data values are valid when \lstinline|tick| is called.  It
+must also expect that imported values may change and that event and
+message handlers are called.
+
+\begin{rationale}
+  The idea behind the \lstinline|tick| call is to hide the complexity
+  of data buffering and MPI transfer from the application.  For
+  efficient data transfer, MUSIC will try to buffer data both at the
+  sending and receiving port in order to send data in large chunks.
+  Internally, MUSIC will use a pre-computed schedule to keep track of
+  at what ticks the actual data transfer should take place and when
+  data should instead be buffered for later transfer.
+\end{rationale}
+
+
+\subsection{Simulation time}
+\index{simulation time}
+
+The method \lstinline|time| returns local time in seconds.
+
+\index{time}
+\begin{head}{time}
+  double runtime::time ()
+\end{head}
+\begin{parameters}
+  \emph{return value} & local time (s) \\
+\end{parameters}
+
+\lstinline|time| returns the local time of last \lstinline|tick|
+call.  Time starts at 0\,s.  While it is possible, and recommended, to
+let MUSIC keep track of time for the application, this is not
+required.
+
+\begin{rationale}
+  To schedule data transfers, MUSIC needs to keep track of the
+  simulation time of all applications via its internal integer
+  representation.  If the application independently manages its own
+  clock, typically by incrementing a floating point variable, there is
+  a risk for drift between the two time representations.  The
+  \lstinline|time| function makes it possible for the application to
+  keep its clock in perfect synchronization with time in the other
+  applications.
+\end{rationale}
+
+
+\subsection{Finalization}
+\index{finalize}
+
+An application supporting MUSIC should replace its call to
+MPI::Finalize with the destruction of the MUSIC runtime object.
+
+\begin{code}{}
+...
+MUSIC::runtime runtime = MUSIC::runtime (setup, stepsize);
+...
+delete runtime;
+\end{code}
+
+\chapter{Adapting Existing Applications}
+
+In this chapter we will highlight the steps necessary to adapt an
+existing neural simulator to MUSIC.  We will assume that the simulator
+is already using MPI to simulate large networks of interconnected
+neurons.
+
+The two main tasks that need to be handled are: firstly, to create and
+map ports for data to be imported and exported, and, secondly, to
+ensure that the \lstinline|tick| function is called at regular
+intervals.
+
+
+\section{Creating and Mapping Ports}
+
+The application needs to inform MUSIC about what data to import and
+export, and where this data resides.  A simulator will typically use
+some sort of script files where the user specifies the model and other
+aspects of the simulation.  If possible, it is desirable to extend the
+scripting language of the simulator so that the user can specify what
+model variables to communicate, and what names to use for ports.
+
+Assuming that we have introduced such constructs into the scripting
+language, we must decide on a suitable point in the initialization
+process where ports should be created and mapped.  Since continuous
+data is read from, or written to, application memory space, the
+program must have allocated its runtime data structures in order to
+perform the mapping.
+
+Communication of spikes will use event ports. Function calls are used
+to send and receive individual spike events.  Sending of spikes is
+relatively straightforward, since the only thing needed is to add a
+call to the method \lstinline|insert_event| at the location where
+spikes are normally detected in the program.  Receiving spikes
+requires more administration, since the spikes can be received earlier
+than when they should reach their destination compartment.  It is
+therefore necessary to save incoming spikes in some sort of sorted
+buffer (typically a priority queue).
+
+\begin{figure}
+  \begin{center}
+    \begin{minipage}[t]{0.45\textwidth}
+      \includegraphics[width=\textwidth]{figures/remapping}
+      \caption[Processing of incoming data]{\label{fig:remapping1}
+        The sender application presents the data to the output port in
+        the same order as it is stored internally.  The receiving
+        application will see the transferred data in the same order
+        and will explicitly have to implement a proper reordering to
+        implement a typical synaptic projection.
+      }
+    \end{minipage}
+    \hfill
+    \begin{minipage}[t]{0.45\textwidth}
+      \includegraphics[width=\textwidth]{figures/remapping2}
+      \caption[Remapping of data within MUSIC]{\label{fig:remapping2}
+        If there is a one-to-one correspondence between sending and
+        receiving neurons, the receiving application can specify an
+        appropriate index map to instruct MUSIC to send the data
+        directly to the right destination.
+      }
+    \end{minipage}
+  \end{center}
+\end{figure}
+
+In addition, MUSIC will always present the spikes as they appear in
+the sending group of neurons.  In most situations, the receiving
+application will want to implement a remapping to the target
+compartments, as illustrated in figure~\ref{fig:remapping1}.  One spike
+may thus end up at multiple postsynaptic compartments, spread out over
+the processors of the receiving application.
+
+In some situations it may be desirable for the receiving application
+to avoid this remapping.  The application can then utilize the different
+forms of mappings available in MUSIC to create a general permutation
+so that MUSIC will send spikes directly to the processor where they
+should be handled.  This situation is illustrated in
+figure~\ref{fig:remapping2}
+
+
+\section{Advancing Simulation Time}
+
+The application must call the \lstinline|tick| function repeatedly
+throughout the simulation.  The application will have to ensure that
+these calls are made at regular intervals, as specified to the runtime
+constructor.  Note that this refers to \emph{simulated time}; there is
+no need to consider how much computation time (``wall clock time'') is
+used between tick calls.
+
+If the application makes use of variable time steps internally, it may
+be necessary to use some sort of checkpoints at fixed intervals where
+tick can be called.  It is not necessary to call tick at every
+integration time step, but the calls should not be too infrequent.
+
+The tick calls are the only times during runtime when MUSIC will use
+MPI.  MUSIC will then use its own communicators, not to interfere with
+the MPI operations of the application.  Still, we recommend that the
+application does not intersperse the tick calls with ongoing MPI
+operations.
+
+
+\section{Initialization and Finalization}
+
+\subsection{Initiate MUSIC}\index{initiate MUSIC}
+
+The idea here is to replace the call to \lstinline|MPI:Init| with a
+call to the \lstinline|MUSIC:setup| constructor.  The setup
+constructor calls \lstinline|MPI:Init| for the application.
+
+The application will have to replace all uses of the global
+communicator \lstinline|MPI::COMM_WORLD| with the communicator
+supplied by MUSIC.  The global communicator will be global over all
+applications and it is necessary to limit the MPI operations to the
+group of MPI processes belonging to the application.
+
+There should be no need to link an application differently when it is
+used together with other applications in a MUSIC setting compared to
+when it is used in a stand-alone setting.  In order to support
+``standard'' operation for the application,
+\lstinline|setup::communicator ()|, therefore, will return
+\lstinline|MPI::COMM_WORLD| if the job is started directly with
+\lstinline|mpirun| instead of with the MUSIC launcher.
+
+
+
+\subsection{Initiate the runtime phase}
+
+Creating the runtime object will implicitly call the \lstinline|setup|
+object destructor to ensure that the application will no longer be
+able to change the communication pattern.  At this stage, MUSIC can
+build the plan for communication between different processes.
+
+\subsection{Finalize MUSIC}\index{finalize}\index{terminate}
+
+The application should also replace its call to
+\lstinline|MPI::Finalize| by the destruction of the runtime object.
+The destructor method will internally call \lstinline|MPI::Finalize|.
+
+\bibliographystyle{unsrtnat}
+\bibliography{music-rfc}
+
+\appendix
+
+\chapter{A Complete Example}
+
+This chapter shows a minimal but still complete example.  It consists
+of two applications, \texttt{waveproducer} and \texttt{waveconsumer},
+and a configuration file used to launch and connect them.
+
+
+\section{Configuration File}
+\label{sec:conffile}
+
+The configuration file starts the waveproducer application on three
+processors and waveconsumer on four.
+
+\lstinputlisting[language=Clean,frame=single]{../test/wavetest.music}
+
+
+\section{Data Generating Application}
+
+\lstinputlisting{../test/waveproducer.cc}
+
+
+\section{Data Consuming Application}
+
+\lstinputlisting{../test/waveconsumer.cc}
+
+
+\chapter{C Interface}
+\label{app:cint}
+
+Most elements of the C interface can be constructed from their C++
+counterparts using a few translation rules:
+
+\begin{enumerate}
+\item All identifiers have the prefix \lstinline|MUSIC_|.
+\item Constructors translate to \lstinline|create_| followed by the
+  class name.
+\item Destructors translate to \lstinline|destroy_| followed by the
+  class name.
+\item Methods translate to class name followed by method name.
+\item References translate to pointers.
+\item Strings translate to \lstinline|char *|.
+\item Optional C++ arguments are required in C.
+\end{enumerate}
+
+Entries which do not strictly follow these rules are preceded with an
+extra comment in the following listing.
+
+\lstinputlisting{music-c-int.h}
+
+\chapter{Specification File Syntax}
+\label{sec:specsyntax}
+
+\newcommand{\nt}[1]{$<$#1$>$}
+
+\begin{tabular}{lcl}
+\nt{simulation spec}   & ::= & \{ \nt{application block} \} \\
+\nt{application block} & ::= & \nt{newline} '[' \nt{application id} ']' \{ \nt{declaration}
+\} \\
+\nt{application id}    & ::= & \nt{symbol} \\
+\nt{declaration}       & ::= & \nt{variable def} $|$ \nt{connection} \\
+\nt{variable def}      & ::= & \nt{variable} '=' \nt{value} \\
+\nt{variable}	       & ::= & \nt{symbol} \\
+\nt{value} 	       & ::= & \nt{integer} $|$ \nt{float} $|$ \nt{string} \\
+\nt{connection}	       & ::= & \nt{port id} \nt{direction} \nt{port id} [ \nt{width} ] \\
+\nt{port id}	       & ::= & \nt{application id} '.' \nt{port} $|$
+\nt{port} \\
+\nt{port}	       & ::= & \nt{symbol} \\
+\nt{direction}	       & ::= & $->$ $|$ $<-$ \\
+\nt{width}	       & ::= & '[' \nt{integer} ']' \\
+\end{tabular}
+
+\printindex
+
+\end{document}
+
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: t
+%%% eval: (flyspell-mode 1)
+%%% eval: (ispell-change-dictionary "american")
+%%% eval: (flyspell-buffer)
+%%% End: 
diff --git a/doc/music.1 b/doc/music.1
new file mode 100644
index 0000000..68a10f6
--- /dev/null
+++ b/doc/music.1
@@ -0,0 +1,70 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH MUSIC 1 "March  5, 2009"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+music \- launch a multi-simulation using MUSIC
+.SH SYNOPSIS
+.B mpirun
+.RI [ mpirun-options ]
+.B  music
+.RI [ options ] " config"
+.br
+.B music
+.RI [ options ] " config" ...
+.SH DESCRIPTION
+This manual page documents briefly the
+.B music
+utility.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBmusic\fP is used to launch a multi-simulation, i.e., an MPI job
+partitioned between a set of parallel programs.  Such programs need to
+be MUSIC-aware (see documentation for the MUSIC library).  MUSIC also
+provides facilities for these programs to exchange data.
+.PP
+The second form of the command above (without \fBmpirun\fP) can be
+used to print out an application rank map or version information.
+.SH OPTIONS
+The
+.B music
+utility follows the usual GNU command line syntax, with long
+options starting with two dashes (`-').
+A summary of options is included below.
+For a complete description, see the MUSIC manual.
+.TP
+.B \-h, \-\-help
+Show summary of options.
+.TP
+.B \-m, \-\-map
+Print application rank map.
+.TP
+.B \-v, \-\-version
+Show version of program.
+.\" .SH SEE ALSO
+.\" .BR bar (1),
+.\" .BR baz (1).
+.\" .br
+.\" The programs are documented fully by
+.\" .IR "The Rise and Fall of a Fooish Bar" ,
+.\" available via the Info system.
+.SH AUTHOR
+MUSIC was written by Mikael Djurfeldt and Örjan Ekeberg for INCF.
+.PP
+This manual page was written by Mikael Djurfeldt <mdj@debian.org>,
+for the Debian project (but may be used by others).
diff --git a/doc/scheduling-algorithm.py b/doc/scheduling-algorithm.py
new file mode 100644
index 0000000..ecd705d
--- /dev/null
+++ b/doc/scheduling-algorithm.py
@@ -0,0 +1,164 @@
+class Node:
+    all = []
+
+    def __init__(self, name, stepSize):
+        Node.all.append(self)
+        self.name = name
+        self.stepSize = stepSize
+        self.connections = []
+
+
+class Connection:
+    all = []
+
+    def __init__(self, pre, post, latency, maxBuffer = 1000):
+        Connection.all.append(self)
+        pre.connections.append(self)
+        self.name = '%s->%s' % (pre.name, post.name)
+        self.pre = pre
+        self.post = post
+        self.latency = latency
+        self.allowedBuffer = maxBuffer
+
+
+# Build a test graph
+
+a = Node('a', 13)
+b = Node('b', 3)
+c = Node('c', 5)
+d = Node('d', 7)
+e = Node('e', 11)
+
+Connection(a, b, 0)
+Connection(b, c, 0)
+Connection(c, d, 8)
+Connection(d, b, 7)
+Connection(c, e, 50)
+Connection(e, b, 50)
+Connection(d, e, 40)
+Connection(e, d, 60)
+
+
+# Search for loops
+
+def depthFirst(x, path):
+    if x.inPath:
+        # Search path to detect beginning of loop
+        for cIndex, c in enumerate(path):
+            if c.pre is x:
+                loop = path[cIndex:]
+
+        print('Found loop', [c.name for c in loop])
+
+        # Compute how much headroom we have for buffering
+        totalDelay = 0
+        for c in loop:
+            totalDelay += c.latency - c.pre.stepSize
+
+        # If negative we will not be able to make it in time
+        # around the loop even without any extra buffering
+        if totalDelay < 0:
+            print('Too short latency (%g) around loop: ' % -totalDelay)
+            print([c.name for c in loop])
+            return False
+
+        # Distribute totalDelay as allowed buffering uniformly over loop
+        # (we could do better by considering constraints form other loops)
+        bufDelay = totalDelay / len(loop)
+        for c in loop:
+            c.allowedBuffer = min(c.allowedBuffer,
+                                  bufDelay // c.pre.stepSize)
+
+        # Calculate and print out debug info
+        print('Distributing delays',
+              [(c.name,
+                bufDelay // c.pre.stepSize,
+                c.allowedBuffer)
+               for c in loop])
+
+        totalBufferedDelay = 0
+        for c in loop:
+            totalBufferedDelay += c.latency - c.pre.stepSize*c.allowedBuffer
+        print('Total buffered delay', totalBufferedDelay)
+
+        return True
+
+    # Mark as processed (remove from main loop forest)
+    x.visited = True
+    x.inPath = True
+
+    # Recurse in depth-first order
+    for c in x.connections:
+        depthFirst(c.post, path+[c])
+
+    x.inPath = False
+
+
+def findLoops(nodeList):
+    for x in nodeList:
+        x.visited = False
+        x.inPath = False
+
+    # Do depth-first traversal of forest
+    for x in nodeList:
+        if not x.visited:
+            depthFirst(x, [])
+
+
+findLoops(Node.all)
+
+for c in Connection.all:
+    print('%s %d'%(c.name, c.allowedBuffer))
+
+
+def simulate(c):
+    s = 0
+    r = 0
+
+    while s < 100:
+        sStart = s
+
+        # Advance receive time as much as possible
+        # still ensuring that oldest data arrives in time
+        while r + c.post.stepSize <= s + c.latency:
+            r += c.post.stepSize
+
+        # Advance send time to match receive time
+        bCount = 0
+        while r + c.post.stepSize >= s + c.latency:
+            s += c.pre.stepSize
+            bCount += 1
+
+        # Advance send time according to precalculated buffer
+        if bCount < c.allowedBuffer:
+            s += c.pre.stepSize * (c.allowedBuffer - bCount)
+
+        print('%s data from %d-%d, sent at %d, received at %d, latency %d (%d)'
+              % (c.name, sStart, s, s, r, r-sStart, c.latency))
+
+
+def simulate_sender(c):
+    s = 0
+    r = 0
+    bCount = 0
+
+    while s < 100:
+        sStart = s
+
+        # Advance receive time as much as possible
+        # still ensuring that oldest data arrives in time
+        while r + c.post.stepSize <= s + c.latency:
+            r += c.post.stepSize
+
+        # Advance send time to match receive time
+        if r + c.post.stepSize < s + c.latency and bCount >= c.allowedBuffer:
+            print('%s data from %d-%d, sent at %d, received at %d, latency %d (%d)'
+                  % (c.name, sStart, s, s, r, r-sStart, c.latency))
+            bCount = 0
+            
+        s += c.pre.stepSize
+        bCount += 1
+
+
+for c in Connection.all:
+    simulate(c)
diff --git a/doc/scheduling.text b/doc/scheduling.text
new file mode 100644
index 0000000..8187dc6
--- /dev/null
+++ b/doc/scheduling.text
@@ -0,0 +1,20 @@
+Implementation of temporal negotiation:
+
+1. XXXConnector constructors stores timing parameters
+
+2. XXXConnector::spatialNegotiation (which constructs the
+subconnectors) passes additional timing parameters to subconnector constructor
+
+3: Phases of temporal negotiation:
+
+3.1 Output subconnectors communicates maxBuffered values to input
+subconnectors
+
+3.2 Input subconnector stores min value of output and input maxBuffered
+
+3.3 Each rank communicates its number of input subconnectors with
+AllToAll
+
+3.4 All timing parameters are communicated using AllToAll
+
+3.5 All ranks run the timing algorithm
diff --git a/examples/.gitignore b/examples/.gitignore
new file mode 100644
index 0000000..cf76d32
--- /dev/null
+++ b/examples/.gitignore
@@ -0,0 +1,2 @@
+waveconsumer
+waveproducer
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..e45a7ef
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,24 @@
+## Process this file with Automake to create Makefile.in
+
+ACLOCAL = $(top_srcdir)/aclocal.sh
+
+exbindir = $(libdir)/@PACKAGE@-@PACKAGE_VERSION@
+exbin_PROGRAMS = waveproducer waveconsumer 	 
+
+exdatadir = $(datadir)/@PACKAGE@-@PACKAGE_VERSION@/examples
+dist_exdata_DATA = messages.music wavetest.music \
+			viewevents.music demo.music demolarge.music \
+			neuronGrid.data neuronGridLARGE.data \
+			spikes0.dat spikes1.dat README
+
+MUSIC_INCLUDE = -I$(top_srcdir)/src -I$(top_builddir)/src
+
+waveproducer_SOURCES = waveproducer.cc
+waveproducer_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+waveproducer_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+waveconsumer_SOURCES = waveconsumer.cc
+waveconsumer_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+waveconsumer_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+MKDEP = gcc -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
diff --git a/examples/README b/examples/README
new file mode 100644
index 0000000..352dec5
--- /dev/null
+++ b/examples/README
@@ -0,0 +1,95 @@
+This directory contains a number of small sample programs and MUSIC
+configuration files.  Each configuration file (with file extension
+.music) is used to launch a set of programs in a multi-simulation.
+The configuration file variable "binary" tells MUSIC which program to
+launch.  Please make sure that such programs exist before you launch
+the simulation.
+
+It is possible to build each program in the standard way for your MPI
+distribution.  You also need to link with the MUSIC library.  This is
+how to build (if it wasn't already built for you automatically) the
+program `clocksource' used in the configuration file contclock.music
+under OpenMPI:
+
+  mpicxx clocksource.cc -lmusic
+
+* Demos
+
+demo.music
+   Random spikes are generated from a 3-process application and
+   sent to a graphics visualizer.
+
+   $ mpirun -np 4 music demo.music
+
+
+demolarge.music
+   Similar to demo.music, but running a larger example on more
+   processors.  20 processes are started by this demo.
+
+   $ mpirun -np 20 music demolarge.music
+
+
+* Event communication
+
+events.music
+   Spikes are sent from a sending to a receiving application.
+
+   $ mpirun -np 4 music events.music
+
+
+fork.music
+   Spikes are sent from one sender to two receiving applications.
+
+   $ mpirun -np 6 music fork.music
+
+
+chain.music
+   Spikes are sent from one sender (running in two processes) to
+   a receiver via an intermediate application which serves as a delay.
+
+   $ mpirun -np 4 music chain.music
+
+
+loop.music
+   Spikes are sent into a loop of two mutually interconnected
+   applications tha both delay and then pass spikes on.
+
+   $ mpirun -np 4 music loop.music
+
+
+* Continuous communication
+
+const.music
+   A constant array of data is sent to a distributed receiving application.
+
+   $ mpirun -np 4 music const.music
+
+
+contclock.music
+   The current simulation time is sent as a test output from one
+   application and received by another.
+
+   $ mpirun -np 2 music contclock.music
+
+
+cloop.music
+   The time signal is sent into a delay loop where values are
+   gradually accumulated.
+
+   $ mpirun -np 4 music cloop.music
+
+
+wavetest.music
+   Send sinusoidal waves from one distributes application
+   to another.  The receiving application writes the result
+   in files named dumpfile0.out, dumpfile1.out and dumpfile2.out.
+
+   $ mpirun -np 7 music wavetest.music
+
+
+* Message communication
+
+messages.music
+   Messages are sent from a sending to a receiving application.
+
+   $ mpirun -np 4 music messages.music
diff --git a/examples/demo.music b/examples/demo.music
new file mode 100644
index 0000000..c5c3124
--- /dev/null
+++ b/examples/demo.music
@@ -0,0 +1,10 @@
+stoptime=100.0
+[from]
+  np=3
+  binary=eventgenerator
+  args=-b 5 27
+[view]
+  np=1
+  binary=viewevents
+  args=-s 1 neuronGrid.data
+  from.out -> view.plot [27]
diff --git a/examples/demolarge.music b/examples/demolarge.music
new file mode 100644
index 0000000..ce328b0
--- /dev/null
+++ b/examples/demolarge.music
@@ -0,0 +1,10 @@
+stoptime=10.0
+[from]
+  np=19
+  binary=eventgenerator
+  args=-b 5 1000
+[view]
+  np=1
+  binary=viewevents
+  args=-s 5 neuronGridLARGE.data
+  from.out -> view.plot [1000]
diff --git a/examples/makeNeuronGrid.m b/examples/makeNeuronGrid.m
new file mode 100644
index 0000000..6166e5c
--- /dev/null
+++ b/examples/makeNeuronGrid.m
@@ -0,0 +1,30 @@
+% makeNeuronGrid.m by Johannes Hjorth
+%
+% This function generates a grid of neurons for use with
+% viewevents.cpp
+%
+% makeNeuronGrid('neuronGrid.data', ...
+%                (-1:1)*150,(-1:1)*150, (-1:1)*150, 30, ...
+%                [0.25 0.53 0.1], [1 0.9 0])
+%
+%makeNeuronGrid('neuronGridPlane.data',(-11:11)*50,(-11:11)*50,0, ...
+%               10, [0.53 0.25 0.1],[0.9 1 0])
+%
+%
+% This version only supports one colour, see VisualiseNeurons for help.
+
+function makeNeuronGrid(filename, x,y,z,r, colMin, colMax)
+
+[X,Y,Z] = meshgrid(x,y,z);
+
+fid = fopen(filename,'w');
+
+fprintf(fid,'1\n');
+fprintf(fid,'%d %d %d\n', colMin);
+fprintf(fid,'%d %d %d\n', colMax);
+
+for i=1:length(X(:))
+  fprintf(fid,'%d %d %d %d 0\n', X(i),Y(i),Z(i),r);
+end
+
+fclose(fid);
diff --git a/examples/makeTestSpikes.m b/examples/makeTestSpikes.m
new file mode 100644
index 0000000..885bee6
--- /dev/null
+++ b/examples/makeTestSpikes.m
@@ -0,0 +1,16 @@
+% makeTestSpikes('viewevents-spikes0.dat',5000,10,1) 
+
+function makeTestSpikes(filename, width, freq, maxTime)
+
+spikeTimes = sort(maxTime*rand(ceil(width*freq*maxTime),1));
+spikeTimes(spikeTimes < 1e-5) = [];
+
+id = floor(width*rand(size(spikeTimes)));
+
+fid = fopen(filename,'w');
+for i=1:length(spikeTimes)
+    fprintf(fid,'%d %d\n', spikeTimes(i), id(i));
+end
+
+fclose(fid);
+
diff --git a/examples/messages.music b/examples/messages.music
new file mode 100644
index 0000000..a23335f
--- /dev/null
+++ b/examples/messages.music
@@ -0,0 +1,9 @@
+np=2
+stoptime=1.0
+[from]
+  binary=messagesource
+  args=-b 1 messages
+[to]
+  binary=eventlogger
+  args=-b 2
+  from.out -> to.message [10]
diff --git a/examples/messages0.dat b/examples/messages0.dat
new file mode 100644
index 0000000..c0f0af8
--- /dev/null
+++ b/examples/messages0.dat
@@ -0,0 +1,2 @@
+0.3	Hello
+0.7	!
diff --git a/examples/messages1.dat b/examples/messages1.dat
new file mode 100644
index 0000000..8268113
--- /dev/null
+++ b/examples/messages1.dat
@@ -0,0 +1,3 @@
+0.5	World
+0.71	Hello World
+0.72	!
diff --git a/examples/neuronGrid.data b/examples/neuronGrid.data
new file mode 100644
index 0000000..72a53cf
--- /dev/null
+++ b/examples/neuronGrid.data
@@ -0,0 +1,32 @@
+2
+2.500000e-01 5.300000e-01 1.000000e-01
+1 9.000000e-01 0
+5.300000e-01 2.500000e-01 1.000000e-01
+0.9 1 0
+-150 -150 -150 30 0
+-150 0 -150 30 0
+-150 150 -150 30 0
+0 -150 -150 30 0
+0 0 -150 30 0
+0 150 -150 30 0
+150 -150 -150 30 0
+150 0 -150 30 0
+150 150 -150 30 0
+-150 -150 0 30 0
+-150 0 0 30 0
+-150 150 0 30 0
+0 -150 0 30 0
+0 0 0 30 1
+0 150 0 30 1
+150 -150 0 30 0
+150 0 0 30 0
+150 150 0 30 0
+-150 -150 150 30 0
+-150 0 150 30 0
+-150 150 150 30 0
+0 -150 150 30 0
+0 0 150 30 1
+0 150 150 30 0
+150 -150 150 30 0
+150 0 150 30 0
+150 150 150 30 0
diff --git a/examples/neuronGridLARGE.data b/examples/neuronGridLARGE.data
new file mode 100644
index 0000000..f170153
--- /dev/null
+++ b/examples/neuronGridLARGE.data
@@ -0,0 +1,1003 @@
+1
+5.300000e-01 2.500000e-01 1
+9.000000e-01 1 0
+-675 -675 -675 20 0
+-675 -525 -675 20 0
+-675 -375 -675 20 0
+-675 -225 -675 20 0
+-675 -75 -675 20 0
+-675 75 -675 20 0
+-675 225 -675 20 0
+-675 375 -675 20 0
+-675 525 -675 20 0
+-675 675 -675 20 0
+-525 -675 -675 20 0
+-525 -525 -675 20 0
+-525 -375 -675 20 0
+-525 -225 -675 20 0
+-525 -75 -675 20 0
+-525 75 -675 20 0
+-525 225 -675 20 0
+-525 375 -675 20 0
+-525 525 -675 20 0
+-525 675 -675 20 0
+-375 -675 -675 20 0
+-375 -525 -675 20 0
+-375 -375 -675 20 0
+-375 -225 -675 20 0
+-375 -75 -675 20 0
+-375 75 -675 20 0
+-375 225 -675 20 0
+-375 375 -675 20 0
+-375 525 -675 20 0
+-375 675 -675 20 0
+-225 -675 -675 20 0
+-225 -525 -675 20 0
+-225 -375 -675 20 0
+-225 -225 -675 20 0
+-225 -75 -675 20 0
+-225 75 -675 20 0
+-225 225 -675 20 0
+-225 375 -675 20 0
+-225 525 -675 20 0
+-225 675 -675 20 0
+-75 -675 -675 20 0
+-75 -525 -675 20 0
+-75 -375 -675 20 0
+-75 -225 -675 20 0
+-75 -75 -675 20 0
+-75 75 -675 20 0
+-75 225 -675 20 0
+-75 375 -675 20 0
+-75 525 -675 20 0
+-75 675 -675 20 0
+75 -675 -675 20 0
+75 -525 -675 20 0
+75 -375 -675 20 0
+75 -225 -675 20 0
+75 -75 -675 20 0
+75 75 -675 20 0
+75 225 -675 20 0
+75 375 -675 20 0
+75 525 -675 20 0
+75 675 -675 20 0
+225 -675 -675 20 0
+225 -525 -675 20 0
+225 -375 -675 20 0
+225 -225 -675 20 0
+225 -75 -675 20 0
+225 75 -675 20 0
+225 225 -675 20 0
+225 375 -675 20 0
+225 525 -675 20 0
+225 675 -675 20 0
+375 -675 -675 20 0
+375 -525 -675 20 0
+375 -375 -675 20 0
+375 -225 -675 20 0
+375 -75 -675 20 0
+375 75 -675 20 0
+375 225 -675 20 0
+375 375 -675 20 0
+375 525 -675 20 0
+375 675 -675 20 0
+525 -675 -675 20 0
+525 -525 -675 20 0
+525 -375 -675 20 0
+525 -225 -675 20 0
+525 -75 -675 20 0
+525 75 -675 20 0
+525 225 -675 20 0
+525 375 -675 20 0
+525 525 -675 20 0
+525 675 -675 20 0
+675 -675 -675 20 0
+675 -525 -675 20 0
+675 -375 -675 20 0
+675 -225 -675 20 0
+675 -75 -675 20 0
+675 75 -675 20 0
+675 225 -675 20 0
+675 375 -675 20 0
+675 525 -675 20 0
+675 675 -675 20 0
+-675 -675 -525 20 0
+-675 -525 -525 20 0
+-675 -375 -525 20 0
+-675 -225 -525 20 0
+-675 -75 -525 20 0
+-675 75 -525 20 0
+-675 225 -525 20 0
+-675 375 -525 20 0
+-675 525 -525 20 0
+-675 675 -525 20 0
+-525 -675 -525 20 0
+-525 -525 -525 20 0
+-525 -375 -525 20 0
+-525 -225 -525 20 0
+-525 -75 -525 20 0
+-525 75 -525 20 0
+-525 225 -525 20 0
+-525 375 -525 20 0
+-525 525 -525 20 0
+-525 675 -525 20 0
+-375 -675 -525 20 0
+-375 -525 -525 20 0
+-375 -375 -525 20 0
+-375 -225 -525 20 0
+-375 -75 -525 20 0
+-375 75 -525 20 0
+-375 225 -525 20 0
+-375 375 -525 20 0
+-375 525 -525 20 0
+-375 675 -525 20 0
+-225 -675 -525 20 0
+-225 -525 -525 20 0
+-225 -375 -525 20 0
+-225 -225 -525 20 0
+-225 -75 -525 20 0
+-225 75 -525 20 0
+-225 225 -525 20 0
+-225 375 -525 20 0
+-225 525 -525 20 0
+-225 675 -525 20 0
+-75 -675 -525 20 0
+-75 -525 -525 20 0
+-75 -375 -525 20 0
+-75 -225 -525 20 0
+-75 -75 -525 20 0
+-75 75 -525 20 0
+-75 225 -525 20 0
+-75 375 -525 20 0
+-75 525 -525 20 0
+-75 675 -525 20 0
+75 -675 -525 20 0
+75 -525 -525 20 0
+75 -375 -525 20 0
+75 -225 -525 20 0
+75 -75 -525 20 0
+75 75 -525 20 0
+75 225 -525 20 0
+75 375 -525 20 0
+75 525 -525 20 0
+75 675 -525 20 0
+225 -675 -525 20 0
+225 -525 -525 20 0
+225 -375 -525 20 0
+225 -225 -525 20 0
+225 -75 -525 20 0
+225 75 -525 20 0
+225 225 -525 20 0
+225 375 -525 20 0
+225 525 -525 20 0
+225 675 -525 20 0
+375 -675 -525 20 0
+375 -525 -525 20 0
+375 -375 -525 20 0
+375 -225 -525 20 0
+375 -75 -525 20 0
+375 75 -525 20 0
+375 225 -525 20 0
+375 375 -525 20 0
+375 525 -525 20 0
+375 675 -525 20 0
+525 -675 -525 20 0
+525 -525 -525 20 0
+525 -375 -525 20 0
+525 -225 -525 20 0
+525 -75 -525 20 0
+525 75 -525 20 0
+525 225 -525 20 0
+525 375 -525 20 0
+525 525 -525 20 0
+525 675 -525 20 0
+675 -675 -525 20 0
+675 -525 -525 20 0
+675 -375 -525 20 0
+675 -225 -525 20 0
+675 -75 -525 20 0
+675 75 -525 20 0
+675 225 -525 20 0
+675 375 -525 20 0
+675 525 -525 20 0
+675 675 -525 20 0
+-675 -675 -375 20 0
+-675 -525 -375 20 0
+-675 -375 -375 20 0
+-675 -225 -375 20 0
+-675 -75 -375 20 0
+-675 75 -375 20 0
+-675 225 -375 20 0
+-675 375 -375 20 0
+-675 525 -375 20 0
+-675 675 -375 20 0
+-525 -675 -375 20 0
+-525 -525 -375 20 0
+-525 -375 -375 20 0
+-525 -225 -375 20 0
+-525 -75 -375 20 0
+-525 75 -375 20 0
+-525 225 -375 20 0
+-525 375 -375 20 0
+-525 525 -375 20 0
+-525 675 -375 20 0
+-375 -675 -375 20 0
+-375 -525 -375 20 0
+-375 -375 -375 20 0
+-375 -225 -375 20 0
+-375 -75 -375 20 0
+-375 75 -375 20 0
+-375 225 -375 20 0
+-375 375 -375 20 0
+-375 525 -375 20 0
+-375 675 -375 20 0
+-225 -675 -375 20 0
+-225 -525 -375 20 0
+-225 -375 -375 20 0
+-225 -225 -375 20 0
+-225 -75 -375 20 0
+-225 75 -375 20 0
+-225 225 -375 20 0
+-225 375 -375 20 0
+-225 525 -375 20 0
+-225 675 -375 20 0
+-75 -675 -375 20 0
+-75 -525 -375 20 0
+-75 -375 -375 20 0
+-75 -225 -375 20 0
+-75 -75 -375 20 0
+-75 75 -375 20 0
+-75 225 -375 20 0
+-75 375 -375 20 0
+-75 525 -375 20 0
+-75 675 -375 20 0
+75 -675 -375 20 0
+75 -525 -375 20 0
+75 -375 -375 20 0
+75 -225 -375 20 0
+75 -75 -375 20 0
+75 75 -375 20 0
+75 225 -375 20 0
+75 375 -375 20 0
+75 525 -375 20 0
+75 675 -375 20 0
+225 -675 -375 20 0
+225 -525 -375 20 0
+225 -375 -375 20 0
+225 -225 -375 20 0
+225 -75 -375 20 0
+225 75 -375 20 0
+225 225 -375 20 0
+225 375 -375 20 0
+225 525 -375 20 0
+225 675 -375 20 0
+375 -675 -375 20 0
+375 -525 -375 20 0
+375 -375 -375 20 0
+375 -225 -375 20 0
+375 -75 -375 20 0
+375 75 -375 20 0
+375 225 -375 20 0
+375 375 -375 20 0
+375 525 -375 20 0
+375 675 -375 20 0
+525 -675 -375 20 0
+525 -525 -375 20 0
+525 -375 -375 20 0
+525 -225 -375 20 0
+525 -75 -375 20 0
+525 75 -375 20 0
+525 225 -375 20 0
+525 375 -375 20 0
+525 525 -375 20 0
+525 675 -375 20 0
+675 -675 -375 20 0
+675 -525 -375 20 0
+675 -375 -375 20 0
+675 -225 -375 20 0
+675 -75 -375 20 0
+675 75 -375 20 0
+675 225 -375 20 0
+675 375 -375 20 0
+675 525 -375 20 0
+675 675 -375 20 0
+-675 -675 -225 20 0
+-675 -525 -225 20 0
+-675 -375 -225 20 0
+-675 -225 -225 20 0
+-675 -75 -225 20 0
+-675 75 -225 20 0
+-675 225 -225 20 0
+-675 375 -225 20 0
+-675 525 -225 20 0
+-675 675 -225 20 0
+-525 -675 -225 20 0
+-525 -525 -225 20 0
+-525 -375 -225 20 0
+-525 -225 -225 20 0
+-525 -75 -225 20 0
+-525 75 -225 20 0
+-525 225 -225 20 0
+-525 375 -225 20 0
+-525 525 -225 20 0
+-525 675 -225 20 0
+-375 -675 -225 20 0
+-375 -525 -225 20 0
+-375 -375 -225 20 0
+-375 -225 -225 20 0
+-375 -75 -225 20 0
+-375 75 -225 20 0
+-375 225 -225 20 0
+-375 375 -225 20 0
+-375 525 -225 20 0
+-375 675 -225 20 0
+-225 -675 -225 20 0
+-225 -525 -225 20 0
+-225 -375 -225 20 0
+-225 -225 -225 20 0
+-225 -75 -225 20 0
+-225 75 -225 20 0
+-225 225 -225 20 0
+-225 375 -225 20 0
+-225 525 -225 20 0
+-225 675 -225 20 0
+-75 -675 -225 20 0
+-75 -525 -225 20 0
+-75 -375 -225 20 0
+-75 -225 -225 20 0
+-75 -75 -225 20 0
+-75 75 -225 20 0
+-75 225 -225 20 0
+-75 375 -225 20 0
+-75 525 -225 20 0
+-75 675 -225 20 0
+75 -675 -225 20 0
+75 -525 -225 20 0
+75 -375 -225 20 0
+75 -225 -225 20 0
+75 -75 -225 20 0
+75 75 -225 20 0
+75 225 -225 20 0
+75 375 -225 20 0
+75 525 -225 20 0
+75 675 -225 20 0
+225 -675 -225 20 0
+225 -525 -225 20 0
+225 -375 -225 20 0
+225 -225 -225 20 0
+225 -75 -225 20 0
+225 75 -225 20 0
+225 225 -225 20 0
+225 375 -225 20 0
+225 525 -225 20 0
+225 675 -225 20 0
+375 -675 -225 20 0
+375 -525 -225 20 0
+375 -375 -225 20 0
+375 -225 -225 20 0
+375 -75 -225 20 0
+375 75 -225 20 0
+375 225 -225 20 0
+375 375 -225 20 0
+375 525 -225 20 0
+375 675 -225 20 0
+525 -675 -225 20 0
+525 -525 -225 20 0
+525 -375 -225 20 0
+525 -225 -225 20 0
+525 -75 -225 20 0
+525 75 -225 20 0
+525 225 -225 20 0
+525 375 -225 20 0
+525 525 -225 20 0
+525 675 -225 20 0
+675 -675 -225 20 0
+675 -525 -225 20 0
+675 -375 -225 20 0
+675 -225 -225 20 0
+675 -75 -225 20 0
+675 75 -225 20 0
+675 225 -225 20 0
+675 375 -225 20 0
+675 525 -225 20 0
+675 675 -225 20 0
+-675 -675 -75 20 0
+-675 -525 -75 20 0
+-675 -375 -75 20 0
+-675 -225 -75 20 0
+-675 -75 -75 20 0
+-675 75 -75 20 0
+-675 225 -75 20 0
+-675 375 -75 20 0
+-675 525 -75 20 0
+-675 675 -75 20 0
+-525 -675 -75 20 0
+-525 -525 -75 20 0
+-525 -375 -75 20 0
+-525 -225 -75 20 0
+-525 -75 -75 20 0
+-525 75 -75 20 0
+-525 225 -75 20 0
+-525 375 -75 20 0
+-525 525 -75 20 0
+-525 675 -75 20 0
+-375 -675 -75 20 0
+-375 -525 -75 20 0
+-375 -375 -75 20 0
+-375 -225 -75 20 0
+-375 -75 -75 20 0
+-375 75 -75 20 0
+-375 225 -75 20 0
+-375 375 -75 20 0
+-375 525 -75 20 0
+-375 675 -75 20 0
+-225 -675 -75 20 0
+-225 -525 -75 20 0
+-225 -375 -75 20 0
+-225 -225 -75 20 0
+-225 -75 -75 20 0
+-225 75 -75 20 0
+-225 225 -75 20 0
+-225 375 -75 20 0
+-225 525 -75 20 0
+-225 675 -75 20 0
+-75 -675 -75 20 0
+-75 -525 -75 20 0
+-75 -375 -75 20 0
+-75 -225 -75 20 0
+-75 -75 -75 20 0
+-75 75 -75 20 0
+-75 225 -75 20 0
+-75 375 -75 20 0
+-75 525 -75 20 0
+-75 675 -75 20 0
+75 -675 -75 20 0
+75 -525 -75 20 0
+75 -375 -75 20 0
+75 -225 -75 20 0
+75 -75 -75 20 0
+75 75 -75 20 0
+75 225 -75 20 0
+75 375 -75 20 0
+75 525 -75 20 0
+75 675 -75 20 0
+225 -675 -75 20 0
+225 -525 -75 20 0
+225 -375 -75 20 0
+225 -225 -75 20 0
+225 -75 -75 20 0
+225 75 -75 20 0
+225 225 -75 20 0
+225 375 -75 20 0
+225 525 -75 20 0
+225 675 -75 20 0
+375 -675 -75 20 0
+375 -525 -75 20 0
+375 -375 -75 20 0
+375 -225 -75 20 0
+375 -75 -75 20 0
+375 75 -75 20 0
+375 225 -75 20 0
+375 375 -75 20 0
+375 525 -75 20 0
+375 675 -75 20 0
+525 -675 -75 20 0
+525 -525 -75 20 0
+525 -375 -75 20 0
+525 -225 -75 20 0
+525 -75 -75 20 0
+525 75 -75 20 0
+525 225 -75 20 0
+525 375 -75 20 0
+525 525 -75 20 0
+525 675 -75 20 0
+675 -675 -75 20 0
+675 -525 -75 20 0
+675 -375 -75 20 0
+675 -225 -75 20 0
+675 -75 -75 20 0
+675 75 -75 20 0
+675 225 -75 20 0
+675 375 -75 20 0
+675 525 -75 20 0
+675 675 -75 20 0
+-675 -675 75 20 0
+-675 -525 75 20 0
+-675 -375 75 20 0
+-675 -225 75 20 0
+-675 -75 75 20 0
+-675 75 75 20 0
+-675 225 75 20 0
+-675 375 75 20 0
+-675 525 75 20 0
+-675 675 75 20 0
+-525 -675 75 20 0
+-525 -525 75 20 0
+-525 -375 75 20 0
+-525 -225 75 20 0
+-525 -75 75 20 0
+-525 75 75 20 0
+-525 225 75 20 0
+-525 375 75 20 0
+-525 525 75 20 0
+-525 675 75 20 0
+-375 -675 75 20 0
+-375 -525 75 20 0
+-375 -375 75 20 0
+-375 -225 75 20 0
+-375 -75 75 20 0
+-375 75 75 20 0
+-375 225 75 20 0
+-375 375 75 20 0
+-375 525 75 20 0
+-375 675 75 20 0
+-225 -675 75 20 0
+-225 -525 75 20 0
+-225 -375 75 20 0
+-225 -225 75 20 0
+-225 -75 75 20 0
+-225 75 75 20 0
+-225 225 75 20 0
+-225 375 75 20 0
+-225 525 75 20 0
+-225 675 75 20 0
+-75 -675 75 20 0
+-75 -525 75 20 0
+-75 -375 75 20 0
+-75 -225 75 20 0
+-75 -75 75 20 0
+-75 75 75 20 0
+-75 225 75 20 0
+-75 375 75 20 0
+-75 525 75 20 0
+-75 675 75 20 0
+75 -675 75 20 0
+75 -525 75 20 0
+75 -375 75 20 0
+75 -225 75 20 0
+75 -75 75 20 0
+75 75 75 20 0
+75 225 75 20 0
+75 375 75 20 0
+75 525 75 20 0
+75 675 75 20 0
+225 -675 75 20 0
+225 -525 75 20 0
+225 -375 75 20 0
+225 -225 75 20 0
+225 -75 75 20 0
+225 75 75 20 0
+225 225 75 20 0
+225 375 75 20 0
+225 525 75 20 0
+225 675 75 20 0
+375 -675 75 20 0
+375 -525 75 20 0
+375 -375 75 20 0
+375 -225 75 20 0
+375 -75 75 20 0
+375 75 75 20 0
+375 225 75 20 0
+375 375 75 20 0
+375 525 75 20 0
+375 675 75 20 0
+525 -675 75 20 0
+525 -525 75 20 0
+525 -375 75 20 0
+525 -225 75 20 0
+525 -75 75 20 0
+525 75 75 20 0
+525 225 75 20 0
+525 375 75 20 0
+525 525 75 20 0
+525 675 75 20 0
+675 -675 75 20 0
+675 -525 75 20 0
+675 -375 75 20 0
+675 -225 75 20 0
+675 -75 75 20 0
+675 75 75 20 0
+675 225 75 20 0
+675 375 75 20 0
+675 525 75 20 0
+675 675 75 20 0
+-675 -675 225 20 0
+-675 -525 225 20 0
+-675 -375 225 20 0
+-675 -225 225 20 0
+-675 -75 225 20 0
+-675 75 225 20 0
+-675 225 225 20 0
+-675 375 225 20 0
+-675 525 225 20 0
+-675 675 225 20 0
+-525 -675 225 20 0
+-525 -525 225 20 0
+-525 -375 225 20 0
+-525 -225 225 20 0
+-525 -75 225 20 0
+-525 75 225 20 0
+-525 225 225 20 0
+-525 375 225 20 0
+-525 525 225 20 0
+-525 675 225 20 0
+-375 -675 225 20 0
+-375 -525 225 20 0
+-375 -375 225 20 0
+-375 -225 225 20 0
+-375 -75 225 20 0
+-375 75 225 20 0
+-375 225 225 20 0
+-375 375 225 20 0
+-375 525 225 20 0
+-375 675 225 20 0
+-225 -675 225 20 0
+-225 -525 225 20 0
+-225 -375 225 20 0
+-225 -225 225 20 0
+-225 -75 225 20 0
+-225 75 225 20 0
+-225 225 225 20 0
+-225 375 225 20 0
+-225 525 225 20 0
+-225 675 225 20 0
+-75 -675 225 20 0
+-75 -525 225 20 0
+-75 -375 225 20 0
+-75 -225 225 20 0
+-75 -75 225 20 0
+-75 75 225 20 0
+-75 225 225 20 0
+-75 375 225 20 0
+-75 525 225 20 0
+-75 675 225 20 0
+75 -675 225 20 0
+75 -525 225 20 0
+75 -375 225 20 0
+75 -225 225 20 0
+75 -75 225 20 0
+75 75 225 20 0
+75 225 225 20 0
+75 375 225 20 0
+75 525 225 20 0
+75 675 225 20 0
+225 -675 225 20 0
+225 -525 225 20 0
+225 -375 225 20 0
+225 -225 225 20 0
+225 -75 225 20 0
+225 75 225 20 0
+225 225 225 20 0
+225 375 225 20 0
+225 525 225 20 0
+225 675 225 20 0
+375 -675 225 20 0
+375 -525 225 20 0
+375 -375 225 20 0
+375 -225 225 20 0
+375 -75 225 20 0
+375 75 225 20 0
+375 225 225 20 0
+375 375 225 20 0
+375 525 225 20 0
+375 675 225 20 0
+525 -675 225 20 0
+525 -525 225 20 0
+525 -375 225 20 0
+525 -225 225 20 0
+525 -75 225 20 0
+525 75 225 20 0
+525 225 225 20 0
+525 375 225 20 0
+525 525 225 20 0
+525 675 225 20 0
+675 -675 225 20 0
+675 -525 225 20 0
+675 -375 225 20 0
+675 -225 225 20 0
+675 -75 225 20 0
+675 75 225 20 0
+675 225 225 20 0
+675 375 225 20 0
+675 525 225 20 0
+675 675 225 20 0
+-675 -675 375 20 0
+-675 -525 375 20 0
+-675 -375 375 20 0
+-675 -225 375 20 0
+-675 -75 375 20 0
+-675 75 375 20 0
+-675 225 375 20 0
+-675 375 375 20 0
+-675 525 375 20 0
+-675 675 375 20 0
+-525 -675 375 20 0
+-525 -525 375 20 0
+-525 -375 375 20 0
+-525 -225 375 20 0
+-525 -75 375 20 0
+-525 75 375 20 0
+-525 225 375 20 0
+-525 375 375 20 0
+-525 525 375 20 0
+-525 675 375 20 0
+-375 -675 375 20 0
+-375 -525 375 20 0
+-375 -375 375 20 0
+-375 -225 375 20 0
+-375 -75 375 20 0
+-375 75 375 20 0
+-375 225 375 20 0
+-375 375 375 20 0
+-375 525 375 20 0
+-375 675 375 20 0
+-225 -675 375 20 0
+-225 -525 375 20 0
+-225 -375 375 20 0
+-225 -225 375 20 0
+-225 -75 375 20 0
+-225 75 375 20 0
+-225 225 375 20 0
+-225 375 375 20 0
+-225 525 375 20 0
+-225 675 375 20 0
+-75 -675 375 20 0
+-75 -525 375 20 0
+-75 -375 375 20 0
+-75 -225 375 20 0
+-75 -75 375 20 0
+-75 75 375 20 0
+-75 225 375 20 0
+-75 375 375 20 0
+-75 525 375 20 0
+-75 675 375 20 0
+75 -675 375 20 0
+75 -525 375 20 0
+75 -375 375 20 0
+75 -225 375 20 0
+75 -75 375 20 0
+75 75 375 20 0
+75 225 375 20 0
+75 375 375 20 0
+75 525 375 20 0
+75 675 375 20 0
+225 -675 375 20 0
+225 -525 375 20 0
+225 -375 375 20 0
+225 -225 375 20 0
+225 -75 375 20 0
+225 75 375 20 0
+225 225 375 20 0
+225 375 375 20 0
+225 525 375 20 0
+225 675 375 20 0
+375 -675 375 20 0
+375 -525 375 20 0
+375 -375 375 20 0
+375 -225 375 20 0
+375 -75 375 20 0
+375 75 375 20 0
+375 225 375 20 0
+375 375 375 20 0
+375 525 375 20 0
+375 675 375 20 0
+525 -675 375 20 0
+525 -525 375 20 0
+525 -375 375 20 0
+525 -225 375 20 0
+525 -75 375 20 0
+525 75 375 20 0
+525 225 375 20 0
+525 375 375 20 0
+525 525 375 20 0
+525 675 375 20 0
+675 -675 375 20 0
+675 -525 375 20 0
+675 -375 375 20 0
+675 -225 375 20 0
+675 -75 375 20 0
+675 75 375 20 0
+675 225 375 20 0
+675 375 375 20 0
+675 525 375 20 0
+675 675 375 20 0
+-675 -675 525 20 0
+-675 -525 525 20 0
+-675 -375 525 20 0
+-675 -225 525 20 0
+-675 -75 525 20 0
+-675 75 525 20 0
+-675 225 525 20 0
+-675 375 525 20 0
+-675 525 525 20 0
+-675 675 525 20 0
+-525 -675 525 20 0
+-525 -525 525 20 0
+-525 -375 525 20 0
+-525 -225 525 20 0
+-525 -75 525 20 0
+-525 75 525 20 0
+-525 225 525 20 0
+-525 375 525 20 0
+-525 525 525 20 0
+-525 675 525 20 0
+-375 -675 525 20 0
+-375 -525 525 20 0
+-375 -375 525 20 0
+-375 -225 525 20 0
+-375 -75 525 20 0
+-375 75 525 20 0
+-375 225 525 20 0
+-375 375 525 20 0
+-375 525 525 20 0
+-375 675 525 20 0
+-225 -675 525 20 0
+-225 -525 525 20 0
+-225 -375 525 20 0
+-225 -225 525 20 0
+-225 -75 525 20 0
+-225 75 525 20 0
+-225 225 525 20 0
+-225 375 525 20 0
+-225 525 525 20 0
+-225 675 525 20 0
+-75 -675 525 20 0
+-75 -525 525 20 0
+-75 -375 525 20 0
+-75 -225 525 20 0
+-75 -75 525 20 0
+-75 75 525 20 0
+-75 225 525 20 0
+-75 375 525 20 0
+-75 525 525 20 0
+-75 675 525 20 0
+75 -675 525 20 0
+75 -525 525 20 0
+75 -375 525 20 0
+75 -225 525 20 0
+75 -75 525 20 0
+75 75 525 20 0
+75 225 525 20 0
+75 375 525 20 0
+75 525 525 20 0
+75 675 525 20 0
+225 -675 525 20 0
+225 -525 525 20 0
+225 -375 525 20 0
+225 -225 525 20 0
+225 -75 525 20 0
+225 75 525 20 0
+225 225 525 20 0
+225 375 525 20 0
+225 525 525 20 0
+225 675 525 20 0
+375 -675 525 20 0
+375 -525 525 20 0
+375 -375 525 20 0
+375 -225 525 20 0
+375 -75 525 20 0
+375 75 525 20 0
+375 225 525 20 0
+375 375 525 20 0
+375 525 525 20 0
+375 675 525 20 0
+525 -675 525 20 0
+525 -525 525 20 0
+525 -375 525 20 0
+525 -225 525 20 0
+525 -75 525 20 0
+525 75 525 20 0
+525 225 525 20 0
+525 375 525 20 0
+525 525 525 20 0
+525 675 525 20 0
+675 -675 525 20 0
+675 -525 525 20 0
+675 -375 525 20 0
+675 -225 525 20 0
+675 -75 525 20 0
+675 75 525 20 0
+675 225 525 20 0
+675 375 525 20 0
+675 525 525 20 0
+675 675 525 20 0
+-675 -675 675 20 0
+-675 -525 675 20 0
+-675 -375 675 20 0
+-675 -225 675 20 0
+-675 -75 675 20 0
+-675 75 675 20 0
+-675 225 675 20 0
+-675 375 675 20 0
+-675 525 675 20 0
+-675 675 675 20 0
+-525 -675 675 20 0
+-525 -525 675 20 0
+-525 -375 675 20 0
+-525 -225 675 20 0
+-525 -75 675 20 0
+-525 75 675 20 0
+-525 225 675 20 0
+-525 375 675 20 0
+-525 525 675 20 0
+-525 675 675 20 0
+-375 -675 675 20 0
+-375 -525 675 20 0
+-375 -375 675 20 0
+-375 -225 675 20 0
+-375 -75 675 20 0
+-375 75 675 20 0
+-375 225 675 20 0
+-375 375 675 20 0
+-375 525 675 20 0
+-375 675 675 20 0
+-225 -675 675 20 0
+-225 -525 675 20 0
+-225 -375 675 20 0
+-225 -225 675 20 0
+-225 -75 675 20 0
+-225 75 675 20 0
+-225 225 675 20 0
+-225 375 675 20 0
+-225 525 675 20 0
+-225 675 675 20 0
+-75 -675 675 20 0
+-75 -525 675 20 0
+-75 -375 675 20 0
+-75 -225 675 20 0
+-75 -75 675 20 0
+-75 75 675 20 0
+-75 225 675 20 0
+-75 375 675 20 0
+-75 525 675 20 0
+-75 675 675 20 0
+75 -675 675 20 0
+75 -525 675 20 0
+75 -375 675 20 0
+75 -225 675 20 0
+75 -75 675 20 0
+75 75 675 20 0
+75 225 675 20 0
+75 375 675 20 0
+75 525 675 20 0
+75 675 675 20 0
+225 -675 675 20 0
+225 -525 675 20 0
+225 -375 675 20 0
+225 -225 675 20 0
+225 -75 675 20 0
+225 75 675 20 0
+225 225 675 20 0
+225 375 675 20 0
+225 525 675 20 0
+225 675 675 20 0
+375 -675 675 20 0
+375 -525 675 20 0
+375 -375 675 20 0
+375 -225 675 20 0
+375 -75 675 20 0
+375 75 675 20 0
+375 225 675 20 0
+375 375 675 20 0
+375 525 675 20 0
+375 675 675 20 0
+525 -675 675 20 0
+525 -525 675 20 0
+525 -375 675 20 0
+525 -225 675 20 0
+525 -75 675 20 0
+525 75 675 20 0
+525 225 675 20 0
+525 375 675 20 0
+525 525 675 20 0
+525 675 675 20 0
+675 -675 675 20 0
+675 -525 675 20 0
+675 -375 675 20 0
+675 -225 675 20 0
+675 -75 675 20 0
+675 75 675 20 0
+675 225 675 20 0
+675 375 675 20 0
+675 525 675 20 0
+675 675 675 20 0
diff --git a/examples/neuronGridPlane.data b/examples/neuronGridPlane.data
new file mode 100644
index 0000000..6e7ceec
--- /dev/null
+++ b/examples/neuronGridPlane.data
@@ -0,0 +1,532 @@
+1
+5.300000e-01 2.500000e-01 1.000000e-01
+9.000000e-01 1 0
+-550 -550 0 10 0
+-550 -500 0 10 0
+-550 -450 0 10 0
+-550 -400 0 10 0
+-550 -350 0 10 0
+-550 -300 0 10 0
+-550 -250 0 10 0
+-550 -200 0 10 0
+-550 -150 0 10 0
+-550 -100 0 10 0
+-550 -50 0 10 0
+-550 0 0 10 0
+-550 50 0 10 0
+-550 100 0 10 0
+-550 150 0 10 0
+-550 200 0 10 0
+-550 250 0 10 0
+-550 300 0 10 0
+-550 350 0 10 0
+-550 400 0 10 0
+-550 450 0 10 0
+-550 500 0 10 0
+-550 550 0 10 0
+-500 -550 0 10 0
+-500 -500 0 10 0
+-500 -450 0 10 0
+-500 -400 0 10 0
+-500 -350 0 10 0
+-500 -300 0 10 0
+-500 -250 0 10 0
+-500 -200 0 10 0
+-500 -150 0 10 0
+-500 -100 0 10 0
+-500 -50 0 10 0
+-500 0 0 10 0
+-500 50 0 10 0
+-500 100 0 10 0
+-500 150 0 10 0
+-500 200 0 10 0
+-500 250 0 10 0
+-500 300 0 10 0
+-500 350 0 10 0
+-500 400 0 10 0
+-500 450 0 10 0
+-500 500 0 10 0
+-500 550 0 10 0
+-450 -550 0 10 0
+-450 -500 0 10 0
+-450 -450 0 10 0
+-450 -400 0 10 0
+-450 -350 0 10 0
+-450 -300 0 10 0
+-450 -250 0 10 0
+-450 -200 0 10 0
+-450 -150 0 10 0
+-450 -100 0 10 0
+-450 -50 0 10 0
+-450 0 0 10 0
+-450 50 0 10 0
+-450 100 0 10 0
+-450 150 0 10 0
+-450 200 0 10 0
+-450 250 0 10 0
+-450 300 0 10 0
+-450 350 0 10 0
+-450 400 0 10 0
+-450 450 0 10 0
+-450 500 0 10 0
+-450 550 0 10 0
+-400 -550 0 10 0
+-400 -500 0 10 0
+-400 -450 0 10 0
+-400 -400 0 10 0
+-400 -350 0 10 0
+-400 -300 0 10 0
+-400 -250 0 10 0
+-400 -200 0 10 0
+-400 -150 0 10 0
+-400 -100 0 10 0
+-400 -50 0 10 0
+-400 0 0 10 0
+-400 50 0 10 0
+-400 100 0 10 0
+-400 150 0 10 0
+-400 200 0 10 0
+-400 250 0 10 0
+-400 300 0 10 0
+-400 350 0 10 0
+-400 400 0 10 0
+-400 450 0 10 0
+-400 500 0 10 0
+-400 550 0 10 0
+-350 -550 0 10 0
+-350 -500 0 10 0
+-350 -450 0 10 0
+-350 -400 0 10 0
+-350 -350 0 10 0
+-350 -300 0 10 0
+-350 -250 0 10 0
+-350 -200 0 10 0
+-350 -150 0 10 0
+-350 -100 0 10 0
+-350 -50 0 10 0
+-350 0 0 10 0
+-350 50 0 10 0
+-350 100 0 10 0
+-350 150 0 10 0
+-350 200 0 10 0
+-350 250 0 10 0
+-350 300 0 10 0
+-350 350 0 10 0
+-350 400 0 10 0
+-350 450 0 10 0
+-350 500 0 10 0
+-350 550 0 10 0
+-300 -550 0 10 0
+-300 -500 0 10 0
+-300 -450 0 10 0
+-300 -400 0 10 0
+-300 -350 0 10 0
+-300 -300 0 10 0
+-300 -250 0 10 0
+-300 -200 0 10 0
+-300 -150 0 10 0
+-300 -100 0 10 0
+-300 -50 0 10 0
+-300 0 0 10 0
+-300 50 0 10 0
+-300 100 0 10 0
+-300 150 0 10 0
+-300 200 0 10 0
+-300 250 0 10 0
+-300 300 0 10 0
+-300 350 0 10 0
+-300 400 0 10 0
+-300 450 0 10 0
+-300 500 0 10 0
+-300 550 0 10 0
+-250 -550 0 10 0
+-250 -500 0 10 0
+-250 -450 0 10 0
+-250 -400 0 10 0
+-250 -350 0 10 0
+-250 -300 0 10 0
+-250 -250 0 10 0
+-250 -200 0 10 0
+-250 -150 0 10 0
+-250 -100 0 10 0
+-250 -50 0 10 0
+-250 0 0 10 0
+-250 50 0 10 0
+-250 100 0 10 0
+-250 150 0 10 0
+-250 200 0 10 0
+-250 250 0 10 0
+-250 300 0 10 0
+-250 350 0 10 0
+-250 400 0 10 0
+-250 450 0 10 0
+-250 500 0 10 0
+-250 550 0 10 0
+-200 -550 0 10 0
+-200 -500 0 10 0
+-200 -450 0 10 0
+-200 -400 0 10 0
+-200 -350 0 10 0
+-200 -300 0 10 0
+-200 -250 0 10 0
+-200 -200 0 10 0
+-200 -150 0 10 0
+-200 -100 0 10 0
+-200 -50 0 10 0
+-200 0 0 10 0
+-200 50 0 10 0
+-200 100 0 10 0
+-200 150 0 10 0
+-200 200 0 10 0
+-200 250 0 10 0
+-200 300 0 10 0
+-200 350 0 10 0
+-200 400 0 10 0
+-200 450 0 10 0
+-200 500 0 10 0
+-200 550 0 10 0
+-150 -550 0 10 0
+-150 -500 0 10 0
+-150 -450 0 10 0
+-150 -400 0 10 0
+-150 -350 0 10 0
+-150 -300 0 10 0
+-150 -250 0 10 0
+-150 -200 0 10 0
+-150 -150 0 10 0
+-150 -100 0 10 0
+-150 -50 0 10 0
+-150 0 0 10 0
+-150 50 0 10 0
+-150 100 0 10 0
+-150 150 0 10 0
+-150 200 0 10 0
+-150 250 0 10 0
+-150 300 0 10 0
+-150 350 0 10 0
+-150 400 0 10 0
+-150 450 0 10 0
+-150 500 0 10 0
+-150 550 0 10 0
+-100 -550 0 10 0
+-100 -500 0 10 0
+-100 -450 0 10 0
+-100 -400 0 10 0
+-100 -350 0 10 0
+-100 -300 0 10 0
+-100 -250 0 10 0
+-100 -200 0 10 0
+-100 -150 0 10 0
+-100 -100 0 10 0
+-100 -50 0 10 0
+-100 0 0 10 0
+-100 50 0 10 0
+-100 100 0 10 0
+-100 150 0 10 0
+-100 200 0 10 0
+-100 250 0 10 0
+-100 300 0 10 0
+-100 350 0 10 0
+-100 400 0 10 0
+-100 450 0 10 0
+-100 500 0 10 0
+-100 550 0 10 0
+-50 -550 0 10 0
+-50 -500 0 10 0
+-50 -450 0 10 0
+-50 -400 0 10 0
+-50 -350 0 10 0
+-50 -300 0 10 0
+-50 -250 0 10 0
+-50 -200 0 10 0
+-50 -150 0 10 0
+-50 -100 0 10 0
+-50 -50 0 10 0
+-50 0 0 10 0
+-50 50 0 10 0
+-50 100 0 10 0
+-50 150 0 10 0
+-50 200 0 10 0
+-50 250 0 10 0
+-50 300 0 10 0
+-50 350 0 10 0
+-50 400 0 10 0
+-50 450 0 10 0
+-50 500 0 10 0
+-50 550 0 10 0
+0 -550 0 10 0
+0 -500 0 10 0
+0 -450 0 10 0
+0 -400 0 10 0
+0 -350 0 10 0
+0 -300 0 10 0
+0 -250 0 10 0
+0 -200 0 10 0
+0 -150 0 10 0
+0 -100 0 10 0
+0 -50 0 10 0
+0 0 0 10 0
+0 50 0 10 0
+0 100 0 10 0
+0 150 0 10 0
+0 200 0 10 0
+0 250 0 10 0
+0 300 0 10 0
+0 350 0 10 0
+0 400 0 10 0
+0 450 0 10 0
+0 500 0 10 0
+0 550 0 10 0
+50 -550 0 10 0
+50 -500 0 10 0
+50 -450 0 10 0
+50 -400 0 10 0
+50 -350 0 10 0
+50 -300 0 10 0
+50 -250 0 10 0
+50 -200 0 10 0
+50 -150 0 10 0
+50 -100 0 10 0
+50 -50 0 10 0
+50 0 0 10 0
+50 50 0 10 0
+50 100 0 10 0
+50 150 0 10 0
+50 200 0 10 0
+50 250 0 10 0
+50 300 0 10 0
+50 350 0 10 0
+50 400 0 10 0
+50 450 0 10 0
+50 500 0 10 0
+50 550 0 10 0
+100 -550 0 10 0
+100 -500 0 10 0
+100 -450 0 10 0
+100 -400 0 10 0
+100 -350 0 10 0
+100 -300 0 10 0
+100 -250 0 10 0
+100 -200 0 10 0
+100 -150 0 10 0
+100 -100 0 10 0
+100 -50 0 10 0
+100 0 0 10 0
+100 50 0 10 0
+100 100 0 10 0
+100 150 0 10 0
+100 200 0 10 0
+100 250 0 10 0
+100 300 0 10 0
+100 350 0 10 0
+100 400 0 10 0
+100 450 0 10 0
+100 500 0 10 0
+100 550 0 10 0
+150 -550 0 10 0
+150 -500 0 10 0
+150 -450 0 10 0
+150 -400 0 10 0
+150 -350 0 10 0
+150 -300 0 10 0
+150 -250 0 10 0
+150 -200 0 10 0
+150 -150 0 10 0
+150 -100 0 10 0
+150 -50 0 10 0
+150 0 0 10 0
+150 50 0 10 0
+150 100 0 10 0
+150 150 0 10 0
+150 200 0 10 0
+150 250 0 10 0
+150 300 0 10 0
+150 350 0 10 0
+150 400 0 10 0
+150 450 0 10 0
+150 500 0 10 0
+150 550 0 10 0
+200 -550 0 10 0
+200 -500 0 10 0
+200 -450 0 10 0
+200 -400 0 10 0
+200 -350 0 10 0
+200 -300 0 10 0
+200 -250 0 10 0
+200 -200 0 10 0
+200 -150 0 10 0
+200 -100 0 10 0
+200 -50 0 10 0
+200 0 0 10 0
+200 50 0 10 0
+200 100 0 10 0
+200 150 0 10 0
+200 200 0 10 0
+200 250 0 10 0
+200 300 0 10 0
+200 350 0 10 0
+200 400 0 10 0
+200 450 0 10 0
+200 500 0 10 0
+200 550 0 10 0
+250 -550 0 10 0
+250 -500 0 10 0
+250 -450 0 10 0
+250 -400 0 10 0
+250 -350 0 10 0
+250 -300 0 10 0
+250 -250 0 10 0
+250 -200 0 10 0
+250 -150 0 10 0
+250 -100 0 10 0
+250 -50 0 10 0
+250 0 0 10 0
+250 50 0 10 0
+250 100 0 10 0
+250 150 0 10 0
+250 200 0 10 0
+250 250 0 10 0
+250 300 0 10 0
+250 350 0 10 0
+250 400 0 10 0
+250 450 0 10 0
+250 500 0 10 0
+250 550 0 10 0
+300 -550 0 10 0
+300 -500 0 10 0
+300 -450 0 10 0
+300 -400 0 10 0
+300 -350 0 10 0
+300 -300 0 10 0
+300 -250 0 10 0
+300 -200 0 10 0
+300 -150 0 10 0
+300 -100 0 10 0
+300 -50 0 10 0
+300 0 0 10 0
+300 50 0 10 0
+300 100 0 10 0
+300 150 0 10 0
+300 200 0 10 0
+300 250 0 10 0
+300 300 0 10 0
+300 350 0 10 0
+300 400 0 10 0
+300 450 0 10 0
+300 500 0 10 0
+300 550 0 10 0
+350 -550 0 10 0
+350 -500 0 10 0
+350 -450 0 10 0
+350 -400 0 10 0
+350 -350 0 10 0
+350 -300 0 10 0
+350 -250 0 10 0
+350 -200 0 10 0
+350 -150 0 10 0
+350 -100 0 10 0
+350 -50 0 10 0
+350 0 0 10 0
+350 50 0 10 0
+350 100 0 10 0
+350 150 0 10 0
+350 200 0 10 0
+350 250 0 10 0
+350 300 0 10 0
+350 350 0 10 0
+350 400 0 10 0
+350 450 0 10 0
+350 500 0 10 0
+350 550 0 10 0
+400 -550 0 10 0
+400 -500 0 10 0
+400 -450 0 10 0
+400 -400 0 10 0
+400 -350 0 10 0
+400 -300 0 10 0
+400 -250 0 10 0
+400 -200 0 10 0
+400 -150 0 10 0
+400 -100 0 10 0
+400 -50 0 10 0
+400 0 0 10 0
+400 50 0 10 0
+400 100 0 10 0
+400 150 0 10 0
+400 200 0 10 0
+400 250 0 10 0
+400 300 0 10 0
+400 350 0 10 0
+400 400 0 10 0
+400 450 0 10 0
+400 500 0 10 0
+400 550 0 10 0
+450 -550 0 10 0
+450 -500 0 10 0
+450 -450 0 10 0
+450 -400 0 10 0
+450 -350 0 10 0
+450 -300 0 10 0
+450 -250 0 10 0
+450 -200 0 10 0
+450 -150 0 10 0
+450 -100 0 10 0
+450 -50 0 10 0
+450 0 0 10 0
+450 50 0 10 0
+450 100 0 10 0
+450 150 0 10 0
+450 200 0 10 0
+450 250 0 10 0
+450 300 0 10 0
+450 350 0 10 0
+450 400 0 10 0
+450 450 0 10 0
+450 500 0 10 0
+450 550 0 10 0
+500 -550 0 10 0
+500 -500 0 10 0
+500 -450 0 10 0
+500 -400 0 10 0
+500 -350 0 10 0
+500 -300 0 10 0
+500 -250 0 10 0
+500 -200 0 10 0
+500 -150 0 10 0
+500 -100 0 10 0
+500 -50 0 10 0
+500 0 0 10 0
+500 50 0 10 0
+500 100 0 10 0
+500 150 0 10 0
+500 200 0 10 0
+500 250 0 10 0
+500 300 0 10 0
+500 350 0 10 0
+500 400 0 10 0
+500 450 0 10 0
+500 500 0 10 0
+500 550 0 10 0
+550 -550 0 10 0
+550 -500 0 10 0
+550 -450 0 10 0
+550 -400 0 10 0
+550 -350 0 10 0
+550 -300 0 10 0
+550 -250 0 10 0
+550 -200 0 10 0
+550 -150 0 10 0
+550 -100 0 10 0
+550 -50 0 10 0
+550 0 0 10 0
+550 50 0 10 0
+550 100 0 10 0
+550 150 0 10 0
+550 200 0 10 0
+550 250 0 10 0
+550 300 0 10 0
+550 350 0 10 0
+550 400 0 10 0
+550 450 0 10 0
+550 500 0 10 0
+550 550 0 10 0
diff --git a/examples/spikes0.dat b/examples/spikes0.dat
new file mode 100644
index 0000000..6de2522
--- /dev/null
+++ b/examples/spikes0.dat
@@ -0,0 +1,11 @@
+# spikes
+0.0	0
+0.1	1
+0.2	2
+0.3	3
+0.4	4
+0.5	5
+0.6	6
+0.7	7
+0.8	8
+0.9	9
diff --git a/examples/spikes1.dat b/examples/spikes1.dat
new file mode 100644
index 0000000..416c637
--- /dev/null
+++ b/examples/spikes1.dat
@@ -0,0 +1,11 @@
+# spikes
+0.0	9
+0.1	0
+0.2	1
+0.3	2
+0.4	3
+0.5	4
+0.6	5
+0.7	6
+0.8	7
+0.9	8
diff --git a/examples/viewevents.music b/examples/viewevents.music
new file mode 100644
index 0000000..db512c5
--- /dev/null
+++ b/examples/viewevents.music
@@ -0,0 +1,9 @@
+np=1
+stoptime=1.0
+[from]
+  binary=eventsource
+  args=-t 1e-4 27 spikes
+[to]
+  binary=viewevents
+  from.out -> to.plot [27]
+  args=-t 1e-4 -s 10.0 neuronGrid.data
diff --git a/examples/vieweventsLARGE.music b/examples/vieweventsLARGE.music
new file mode 100644
index 0000000..421ab23
--- /dev/null
+++ b/examples/vieweventsLARGE.music
@@ -0,0 +1,9 @@
+np=1
+stoptime=1.0
+[from]
+  binary=eventsource
+  args=-t 1e-4 1000 viewevents2-spikes
+[to]
+  binary=viewevents
+  from.out -> to.plot [1000]
+  args=-t 1e-4 -s 10.0 neuronGridLARGE.data
diff --git a/examples/vieweventsPlane.music b/examples/vieweventsPlane.music
new file mode 100644
index 0000000..48b57e1
--- /dev/null
+++ b/examples/vieweventsPlane.music
@@ -0,0 +1,9 @@
+np=1
+stoptime=1.0
+[from]
+  binary=eventsource
+  args=-t 1e-3 529 viewevents-spikes
+[to]
+  binary=viewevents
+  from.out -> to.plot [529]
+  args=-t 1e-3 -s 100.0 -T Cortex neuronGridPlane.data
diff --git a/examples/waveconsumer.cc b/examples/waveconsumer.cc
new file mode 100644
index 0000000..bd8e650
--- /dev/null
+++ b/examples/waveconsumer.cc
@@ -0,0 +1,59 @@
+#include <mpi.h>
+#include <music.hh>
+#include <fstream>
+#include <sstream>
+
+#define TIMESTEP 0.0005
+
+MPI::Intracomm comm;
+double* data;
+
+int
+main (int args, char* argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (args, argv);
+
+  MUSIC::ContInputPort* wavedata =
+    setup->publishContInput ("wavedata");
+
+  comm = setup->communicator ();
+  int nProcesses = comm.Get_size (); // how many processes are there?
+  int rank = comm.Get_rank ();       // which process am I?
+  int width = 0;
+  if (wavedata->hasWidth ())
+    width = wavedata->width ();
+  else
+    comm.Abort (1);
+
+  // For clarity, assume that width is a multiple of n_processes
+  int nLocalVars = width / nProcesses;
+  data = new double[nLocalVars];
+  std::ostringstream filename;
+  filename << argv[1] << rank << ".out";
+  std::ofstream file (filename.str ().data ());
+    
+  // Declare where in memory to put data
+  MUSIC::ArrayData dmap (data,
+			 MPI::DOUBLE,
+			 rank * nLocalVars,
+			 nLocalVars);
+  wavedata->map (&dmap);
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, TIMESTEP);
+  for (int j =0; runtime->time () < stoptime; j++)
+    {
+	  runtime->tick ();
+      // Dump to file
+      for (int i = 0; i < nLocalVars; ++i)
+    	  file << data[i] << ' ';
+      file << std::endl;
+
+    }
+  runtime->finalize ();
+  
+  delete runtime;
+
+  return 0;
+}
diff --git a/examples/waveproducer.cc b/examples/waveproducer.cc
new file mode 100644
index 0000000..114582c
--- /dev/null
+++ b/examples/waveproducer.cc
@@ -0,0 +1,64 @@
+#include <mpi.h>
+#include <cstdlib>
+#include <cmath>
+#include <music.hh>
+
+#define TIMESTEP 0.001
+
+MPI::Intracomm comm;
+double* data;
+
+int
+main (int argc, char* argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  
+  int width = atoi (argv[1]); // command line arg gives width
+
+  MUSIC::ContOutputPort* wavedata =
+    setup->publishContOutput ("wavedata");
+
+  comm = setup->communicator ();
+  int nProcesses = comm.Get_size (); // how many processes are there?
+  int rank = comm.Get_rank ();       // which process am I?
+
+  // For clarity, assume that width is a multiple of n_processes
+  int nLocalVars = width / nProcesses;
+  data = new double[nLocalVars];
+  for (int i = 0; i < nLocalVars; ++i)
+    data[i] = 0.0;
+    
+  // Declare what data we have to export
+  MUSIC::ArrayData dmap (data,
+			 MPI::DOUBLE,
+			 rank * nLocalVars,
+			 nLocalVars);
+  wavedata->map (&dmap);
+  
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, TIMESTEP);
+
+  for (; runtime->time () < stoptime; runtime->tick ())
+    {
+      if (rank == 0)
+	{
+	  // Generate original data on master node
+	  int i;
+	  double time = runtime->time ();
+
+	  for (i = 0; i < nLocalVars; ++i)
+	    data[i] = sin (2 * M_PI * time * i);
+	}
+
+      // Broadcast these data out to all nodes
+      comm.Bcast (data, nLocalVars, MPI::DOUBLE, 0);
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/examples/wavetest.music b/examples/wavetest.music
new file mode 100644
index 0000000..47452cf
--- /dev/null
+++ b/examples/wavetest.music
@@ -0,0 +1,10 @@
+stoptime=1.0
+[producer]
+  binary=waveproducer
+  args=120
+  np=4
+[consumer]
+  binary=waveconsumer
+  args=dumpfile
+  np=3
+  producer.wavedata -> wavedata[120]
diff --git a/extras/Makefile.am b/extras/Makefile.am
new file mode 100644
index 0000000..22048af
--- /dev/null
+++ b/extras/Makefile.am
@@ -0,0 +1,7 @@
+## Process this file with Automake to create Makefile.in
+
+EXTRA_DIST = music_mpirun
+
+install-data-hook:
+	@INSTALL_PROGRAM@ $(srcdir)/music@LAUNCHSTYLE@ $(DESTDIR)$(bindir)/MUSIC
+
diff --git a/extras/music_mpirun b/extras/music_mpirun
new file mode 100755
index 0000000..a95a021
--- /dev/null
+++ b/extras/music_mpirun
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+if [ $# -ne 2 ]; then
+   echo "Usage: music_openmpi <number of tasks> <configuration file (*.music)>"
+   exit 1
+fi
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+binary=`mpirun -np $1 $path/music $2`
+exitcode=$?
+
+if [ $exitcode -ne 0 ]; then
+   echo "$binary"
+   exit $exitcode
+fi
+
+echo "$binary"
+exit $exitcode
\ No newline at end of file
diff --git a/mpidep/.gitignore b/mpidep/.gitignore
new file mode 100644
index 0000000..736099e
--- /dev/null
+++ b/mpidep/.gitignore
@@ -0,0 +1,5 @@
+/Makefile
+/Makefile.in
+/TAGS
+/.deps
+/core
diff --git a/mpidep/ChangeLog b/mpidep/ChangeLog
new file mode 100644
index 0000000..2cac5ba
--- /dev/null
+++ b/mpidep/ChangeLog
@@ -0,0 +1,62 @@
+2012-08-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* mpidep.cc (getRank): CRAY_XE -> CRAY_XE6; ifstream -> std::ifstream
+
+
+2011-03-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* mpidep.cc (getRank): Support for Cray XE6.  (However, execvp in
+	the music launcher does not work on Cray.  Use option -e.)
+
+2010-07-28  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.7
+
+2009-10-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.6
+
+2009-10-24  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.5
+
+2009-10-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* mpidep.cc (getRank): Support for MPICH 2.  (Thanks to Eilif
+	Müller.)
+
+2009-10-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* mpidep.cc (getRank): Handle rank 0 and correctly detect cases
+	where command line has unexpected form.
+
+2009-04-01  Mikael Djurfeldt  <djurfeldt@nada.kth.se>
+
+	* Release 1.0.4
+
+2009-03-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.3
+
+2009-03-12  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.2
+
+2009-03-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.1
+
+2009-03-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* mpidep.cc (getConfig): Don't reports errors here.  Leave that to
+	utils/music.cc; Skip optional arguments when looking for config
+	file name.
+
+2009-03-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0
+
+2009-02-11  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am, mpidep.hh, mpidep.cc: New files.
+
diff --git a/mpidep/Makefile.am b/mpidep/Makefile.am
new file mode 100644
index 0000000..a8d7070
--- /dev/null
+++ b/mpidep/Makefile.am
@@ -0,0 +1,11 @@
+## Process this file with Automake to create Makefile.in
+
+ACLOCAL = $(top_srcdir)/aclocal.sh
+
+noinst_LTLIBRARIES = libmpidep.la
+
+libmpidep_la_SOURCES = mpidep.cc mpidep.hh
+libmpidep_la_CXXFLAGS = -I$(top_srcdir)/src -I$(top_srcdir) @MPI_CXXFLAGS@
+
+
+MKDEP = gcc -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
diff --git a/mpidep/mpidep.cc b/mpidep/mpidep.cc
new file mode 100644
index 0000000..d6ac0e9
--- /dev/null
+++ b/mpidep/mpidep.cc
@@ -0,0 +1,201 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string>
+#include <cstring>
+#include <sstream>
+#include <fstream>
+
+extern "C" {
+#include <stdlib.h>
+}
+
+#include "mpidep.hh"
+
+// Implementation-dependent code
+
+#ifndef CRAY_XE6
+#ifdef HAVE_RTS_GET_PERSONALITY
+#define BGL
+#else
+#ifdef HAVE_OMPI_COMM_FREE
+#define OPENMPI
+#else
+#ifdef HAVE_MPICH2
+#define MPICH2
+#else
+#define MPICH
+#endif
+#endif
+#endif
+#endif
+
+#ifdef BGL
+#include <rts.h>
+#endif
+
+#ifdef CRAY_XE6
+extern "C" {
+#include <sched.h>
+}
+#endif
+
+/*
+ * Predict the local MPI process rank before having called MPI::Init
+ *
+ * MPI implementations typically passes meta information either through
+ * argc and argv (MPICH) or through the environment (OpenMPI).
+ *
+ * return -1 on failure
+ */ 
+
+int
+getRank (int argc, char *argv[])
+{
+#ifdef BGL
+  BGLPersonality p;
+  rts_get_personality (&p, sizeof (p));
+  int pid = rts_get_processor_id ();
+  unsigned int rank, np;
+  rts_rankForCoordinates (p.xCoord, p.yCoord, p.zCoord, pid, &rank, &np);
+  return rank;
+#endif
+#ifdef MPICH2
+  char *pmi_rank = getenv("PMI_RANK");
+  int rank;
+  if (pmi_rank==NULL)
+    return -1;
+  else {
+    rank = atoi(pmi_rank);
+    if (rank<0) return -1;
+    return rank;
+  }
+#endif
+#ifdef MPICH
+  int seenP4arg = 0;
+  int rank;
+  const std::string rankopt = "-p4rmrank";
+  for (int i = argc - 2; i > 0; --i)
+    {
+      if (!strncmp (argv[i], "-p4", 3))
+	seenP4arg = 1;
+      if (argv[i] == rankopt)
+	{
+	  std::istringstream iss (argv[i + 1]);
+	  iss >> rank;
+	  return rank;
+	}
+    }
+  return seenP4arg ? 0 : -1;
+#endif
+#ifdef OPENMPI
+  char* vpid = getenv ("OMPI_MCA_ns_nds_vpid");
+  if (vpid == NULL)
+    vpid = getenv ("OMPI_COMM_WORLD_RANK");
+  if (vpid == NULL)
+    return -1;
+  std::istringstream iss (vpid);
+  int rank;
+  iss >> rank;
+  return rank;
+#endif
+#ifdef CRAY_XE6
+  std::ifstream fnid ("/proc/cray_xt/nid");
+  int nid;
+  fnid >> nid;
+  fnid.close ();
+  std::ifstream fnids (getenv ("MUSIC_NODEFILE"));
+  int n = 0;
+  int i;
+  while (fnids)
+    {
+      fnids >> i;
+      if (i == nid)
+	{
+	  int core = sched_getcpu ();
+	  return 24 * n + core;
+	}
+      ++n;
+    }
+  return -1;
+#endif
+}
+
+
+#ifdef MPICH
+std::string
+getSharedDir ()
+{
+  std::ostringstream dirname;
+  char* musicSharedDir = getenv ("MUSIC_SHARED_DIR");
+  if (musicSharedDir)
+    dirname << musicSharedDir;
+  else
+    {
+      char* home = getenv ("HOME");
+      dirname << home;
+    }
+  return dirname.str ();
+}
+#endif
+
+
+std::string
+getFirstArg (int argc, char** argv)
+{
+  for (int i = 1; i < argc; ++i)
+    if (*argv[i] != '-') // skip options
+      return argv[i];
+  return "";
+}
+
+
+/*
+ * Retrieve first argument (the name of the music configuration file)
+ * given to the music utility.
+ *
+ * Be robust against rank == -1 (which occurs when getRank fails).
+ */
+
+std::istream*
+getConfig (int rank, int argc, char** argv)
+{
+#ifdef MPICH
+  std::ostringstream fname;
+  fname << getSharedDir () << "/.musicconf";
+  std::string confname;
+  if (rank == 0)
+    {
+      std::ofstream f (fname.str ().c_str ());
+      confname = getFirstArg (argc, argv);
+      f << confname;
+    }
+  else if (rank > 0)
+    {
+      std::ifstream f (fname.str ().c_str ());
+      f >> confname;
+    }
+  else // rank == -1
+    confname = getFirstArg (argc, argv);
+  return new std::ifstream (confname.c_str ());
+#else
+  return new std::ifstream (getFirstArg (argc, argv).c_str ());
+#endif
+}
diff --git a/mpidep/mpidep.hh b/mpidep/mpidep.hh
new file mode 100644
index 0000000..30862a8
--- /dev/null
+++ b/mpidep/mpidep.hh
@@ -0,0 +1,27 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_MPIDEP_HH
+
+#include <iostream>
+
+int getRank (int argc, char *argv[]);
+std::istream* getConfig (int rank, int argc, char** argv);
+
+#define MUSIC_MPIDEP_HH
+#endif
diff --git a/music/.gitignore b/music/.gitignore
new file mode 100644
index 0000000..0eb9393
--- /dev/null
+++ b/music/.gitignore
@@ -0,0 +1 @@
+/predict_rank.py
diff --git a/music/ChangeLog b/music/ChangeLog
new file mode 100644
index 0000000..d96b340
--- /dev/null
+++ b/music/ChangeLog
@@ -0,0 +1,8 @@
+2012-03-15  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* __init__.py, predict_rank.py: New files.
+
+	* config.py: Renamed from music.py.
+
+	* music.py: New file.
+	(configure): New function.
diff --git a/music/Makefile.am b/music/Makefile.am
new file mode 100644
index 0000000..b5bb964
--- /dev/null
+++ b/music/Makefile.am
@@ -0,0 +1,10 @@
+edit = sed -e 's|@libdir[@]|$(libdir)|g'
+
+pkgpython_PYTHON = __init__.py predict_rank.py config.py
+
+EXTRA_DIST = predict_rank.py.in
+
+predict_rank.py: Makefile predict_rank.py.in
+	rm -f $@ $@.tmp
+	$(edit) $${srcdir}$@.in >$@.tmp
+	mv $@.tmp $@
diff --git a/music/__init__.py b/music/__init__.py
new file mode 100644
index 0000000..35c1a79
--- /dev/null
+++ b/music/__init__.py
@@ -0,0 +1,21 @@
+#
+#  This file is part of MUSIC.
+#  Copyright (C) 2012 Mikael Djurfeldt
+#
+#  MUSIC 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; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  MUSIC 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 should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from predict_rank import predictRank
+from config import launchedByMusic, supersedeArgv, postponeSetup, \
+                   define, Application, connect, configure, launch
diff --git a/music/config.py b/music/config.py
new file mode 100644
index 0000000..e7a3b81
--- /dev/null
+++ b/music/config.py
@@ -0,0 +1,250 @@
+#
+#  This file is part of MUSIC.
+#  Copyright (C) 2012 Mikael Djurfeldt
+#
+#  MUSIC 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; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  MUSIC 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 should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# This API allows for querying the MPI rank and specification of the
+# information in MUSIC configuration files
+
+import os
+
+from music.predict_rank import predictRank
+
+# This function now defined in predict_rank.py
+#
+#def predictRank ():
+#    """
+#    Returns the predicted MPI rank of this process
+#    
+#    :rtype: Integer
+#    """
+#    return 0
+
+CONFIGVARNAME = '_MUSIC_CONFIG_'
+
+OUTPUT = '0'
+INPUT = '1'
+
+
+def launchedByMusic ():
+    return CONFIGVARNAME in os.environ
+
+
+def supersedeArgv (argv):
+    """
+    Replace argc and argv before MUSIC initialization
+    """
+    # Should insert escape characters
+    args = argv[0]
+    for arg in argv[1:]:
+        args += ' ' + arg
+    os.environ['MUSIC_ARGV'] = args
+
+
+def postponeSetup ():
+    """
+    Postpones processing of configuration info until the creation of
+    the first port.  Must be called before creation of MUSIC::Setup.
+    """
+    if not thisApp:
+        raise RuntimeError, \
+              'must define Application before calling postponeSetup ()'
+    os.environ[CONFIGVARNAME] = 'POSTPONE:' + str (thisApp.number)
+
+
+portCodes = {}
+code = 0
+
+def portCode (appName, portName):
+    global code
+    key = (appName, portName)
+    if key in portCodes:
+        return portCodes[key]
+    portCodes[key] = code
+    ans = code
+    code += 1
+    return ans
+
+
+class ConnectivityMap (object):
+    def __init__ (self):
+        self.ports = {}
+    
+    def register (self, portName, direction, width, *connection):
+        if portName in self.ports:
+            (direction_, width_, connections) = self.ports[portName]
+            #*fixme* error checks here
+        else:
+            connections = []
+            self.ports[portName] = (direction, width, connections)
+        connections.append (connection)
+
+    def conf (self):
+        conf = str (len (self.ports))
+        for portName in self.ports:
+            (direction, width, connections) = self.ports[portName]
+            conf += ':' + portName + ':' + direction + ':' + width
+            conf += ':' + str (len (connections))
+            for connection in connections:
+                for item in connection:
+                    conf += ':' + item
+        return conf
+
+
+configDict = {}
+appNumber = 0
+rankSum = 0
+thisRank = predictRank ()
+thisApp = None
+
+class Application (object):
+    def __init__ (self, np = None, binary = None, args = None, name = None):
+        global appNumber, rankSum, thisApp
+        self.name = name
+        self.number = appNumber
+        appNumber += 1
+        self.np = np
+        self.leader = rankSum
+        rankSum += np
+        self.this = False
+        if self.leader <= thisRank and thisRank < rankSum:
+            self.this = True
+            thisApp = self
+
+        self.configDict = {}
+        self.connectivityMap = ConnectivityMap ()
+
+        if binary:
+            self.define ('binary', binary)
+        if args:
+            self.define ('args', args)
+
+        applicationMap.register (self)
+
+    def __getitem__ (self, varName):
+        if varName in self.configDict:
+            return self.configDict[varName]
+        return configDict[varName]
+    
+    def define (self, varName, value):
+        """
+        Define configuration variable varName to value value.
+        """
+        self.configDict[varName] = str (value)
+
+    def connect (self, fromPort, toApp, toPort, width):
+        """
+        Connect fromPort to toPort.
+        """
+        connections.append ((self, fromPort, toApp, toPort, str (width)))
+
+
+class ApplicationMap (object):
+    def __init__ (self):
+        self.applications = []
+        self.nameMap = {}
+
+    def register (self, app):
+        if not app.name:
+            app.name = 'application'
+        if app.name in self.nameMap:
+            # Adjust the name to become unique
+            record = self.nameMap[app.name]
+            base, suffix = record
+            if base == app.name:
+                suffix += 1
+                record[1] = suffix
+            else:
+                base = app.name
+                suffix = 0
+                self.nameMap[base] = [base, suffix]
+            app.name += str (suffix)
+        else:
+            self.nameMap[app.name] = [app.name, 0]
+        self.applications.append (app)
+    
+    def conf (self):
+        conf = str (len (self.applications))
+        for app in self.applications:
+            conf += ':' + app.name + ':' + str (app.np)
+        return conf
+
+applicationMap = ApplicationMap ()
+
+
+def define (varName, value):
+    """
+    Define configuration variable varName to value value.
+    """
+    configDict[varName] = str (value)
+
+
+# Communication algorithms
+    
+commAlgorithms =  { 'collective' : 0, 'point-to-point' : 1 }
+
+# Processing methods
+
+procMethods = { 'tree' : 0, 'table' : 1 }
+
+
+def connect (fromApp, fromPort, toApp, toPort, width,
+             commAlgName = 'collective', procMethodName = 'table'):
+    """
+    Connect fromPort to toPort specifying port width width.
+    """
+    width = str (width)
+    commAlg = commAlgorithms[commAlgName]
+    procMethod = procMethods[procMethodName]
+    fromApp.connectivityMap.register (fromPort, OUTPUT, width,
+                                      toApp.name, toPort,
+                                      str (portCode (toApp.name, toPort)),
+                                      str (toApp.leader), str (toApp.np),
+                                      str (commAlg), str (procMethod))
+    toApp.connectivityMap.register (toPort, INPUT, width,
+                                    toApp.name, toPort,
+                                    str (portCode (toApp.name, toPort)),
+                                    str (fromApp.leader), str (fromApp.np),
+                                    str (commAlg), str (procMethod))
+
+
+configured = False
+
+def configure ():
+    """
+    Configure the MUSIC library using the information provided by
+    define and connect.
+    """
+    conf = thisApp.name \
+           + ':' + str (thisApp.number) \
+           + ':' + applicationMap.conf () \
+           + ':' + thisApp.connectivityMap.conf ()
+
+    configDict.update (thisApp.configDict)
+
+    for key in configDict:
+        conf += ':' + key + '=' + configDict[key]
+
+    os.environ[CONFIGVARNAME] = conf
+
+    configured = True
+
+    
+def launch ():
+    if not configured:
+        configure ()
+    binary = thisApp['binary']
+    os.execvp (binary, [binary] + thisApp['args'].split (' '))
diff --git a/music/get_rank.py b/music/get_rank.py
new file mode 100644
index 0000000..35ca748
--- /dev/null
+++ b/music/get_rank.py
@@ -0,0 +1,29 @@
+
+import ctypes
+import sys
+
+def c_argc_argv (argv):
+    """ convert python argv into ctypes (int argc, char**argv) """
+
+    from ctypes import c_char_p, c_int
+
+    argc = len (argv)
+
+    # char*[] type
+    t_argv = c_char_p*argc
+
+    # construct argv for C
+    c_argv = t_argv (*tuple([c_char_p(arg) for arg in argv]))
+    c_argc = c_int (argc)
+
+    return (c_argc, c_argv)
+
+
+libmusic = ctypes.CDLL ("/opt/music/lib/libmusic-c.so")
+
+
+x = libmusic.MUSIC_predictRank (*c_argc_argv (sys.argv))
+    
+print x
+
+
diff --git a/music/predict_rank.py.in b/music/predict_rank.py.in
new file mode 100644
index 0000000..4266d45
--- /dev/null
+++ b/music/predict_rank.py.in
@@ -0,0 +1,23 @@
+import ctypes
+import sys
+
+def c_argc_argv (argv):
+    """ convert python argv into ctypes (int argc, char**argv) """
+
+    from ctypes import c_char_p, c_int
+
+    argc = len (argv)
+
+    # char*[] type
+    t_argv = c_char_p*argc
+
+    # construct argv for C
+    c_argv = t_argv (*tuple([c_char_p(arg) for arg in argv]))
+    c_argc = c_int (argc)
+
+    return (c_argc, c_argv)
+
+libmusic = ctypes.CDLL ("@libdir@/libmusic-c.so")
+
+def predictRank ():
+    return libmusic.MUSIC_predictRank (*c_argc_argv (sys.argv))
diff --git a/pymusic-old/Makefile b/pymusic-old/Makefile
new file mode 100644
index 0000000..ed2aa34
--- /dev/null
+++ b/pymusic-old/Makefile
@@ -0,0 +1,8 @@
+
+
+LIB=-lpython2.5 -lmpi_cxx -lmpi -lopen-rte -lopen-pal
+INCLUDE=-I/usr/include/python2.5
+
+python4openmpi: python_main.c
+	g++ -fPIC -O2 -c python_main.c -o python_main.o ${INCLUDE}
+	g++ python_main.o -o python4openmpi ${LIB}
diff --git a/pymusic-old/README b/pymusic-old/README
new file mode 100644
index 0000000..659bac3
--- /dev/null
+++ b/pymusic-old/README
@@ -0,0 +1,6 @@
+1. Edit paths in setup.py
+2. python setup.py build_ext --inplace
+3. Edit paths and libraries in Makefile
+4. make
+5. mpirun -np 4 music helloworld.music
+
diff --git a/pymusic-old/helloworld b/pymusic-old/helloworld
new file mode 100755
index 0000000..f56f6ba
--- /dev/null
+++ b/pymusic-old/helloworld
@@ -0,0 +1,2 @@
+#!/bin/bash
+./python4openmpi helloworld.py
diff --git a/pymusic-old/helloworld.music b/pymusic-old/helloworld.music
new file mode 100644
index 0000000..e1c0d91
--- /dev/null
+++ b/pymusic-old/helloworld.music
@@ -0,0 +1,7 @@
+np=2
+[A]
+  binary=./helloworld
+  args=hey
+[B]
+  binary=./helloworld
+  args=ho
diff --git a/pymusic-old/helloworld.py b/pymusic-old/helloworld.py
new file mode 100644
index 0000000..a1f0045
--- /dev/null
+++ b/pymusic-old/helloworld.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+"""
+MUSIC Hello World
+"""
+
+import sys, music
+setup = music.Setup (sys.argv)
+from mpi4py import MPI
+
+hwmess = "Hello, World! I am process %d of %d with argument %s.\n"
+comm = setup.communicator ()
+myrank = comm.Get_rank()
+nprocs = comm.Get_size()
+sys.stdout.write(hwmess % (myrank, nprocs, sys.argv[1]))
+
+# Entering runtime phase
+runtime = music.Runtime (setup, 1e-4)
+
+# Must end with a call to finalize ()
+runtime.finalize ()
diff --git a/pymusic-old/late.h b/pymusic-old/late.h
new file mode 100644
index 0000000..73dbca4
--- /dev/null
+++ b/pymusic-old/late.h
@@ -0,0 +1,8 @@
+#include <mpi.h>
+
+#include "Python.h"
+
+extern PyObject* (*wrapIntracomm_ptr) (MPI_Comm comm);
+
+struct _mpi_message_t;
+typedef _mpi_message_t* MPI_Message; /* ??? */
diff --git a/pymusic-old/late.pxd b/pymusic-old/late.pxd
new file mode 100644
index 0000000..a0c5819
--- /dev/null
+++ b/pymusic-old/late.pxd
@@ -0,0 +1,11 @@
+from mpi4py.libmpi cimport *
+from mpi4py.MPI cimport *
+
+ctypedef object wrapIntracomm_func (MPI_Comm comm)
+
+cdef extern from "late.h":
+    cdef wrapIntracomm_func* wrapIntracomm_ptr
+
+# Local Variables:
+# mode: python
+# End:
diff --git a/pymusic-old/late.pyx b/pymusic-old/late.pyx
new file mode 100644
index 0000000..867e68b
--- /dev/null
+++ b/pymusic-old/late.pyx
@@ -0,0 +1,12 @@
+from late cimport *
+
+cdef wrapIntracomm (MPI_Comm comm):
+    cdef Intracomm icomm = Intracomm ()
+    icomm.ob_mpi = comm
+    return icomm
+
+wrapIntracomm_ptr = wrapIntracomm
+
+# Local Variables:
+# mode: python
+# End:
diff --git a/pymusic-old/late_impl.h b/pymusic-old/late_impl.h
new file mode 100644
index 0000000..fd2c658
--- /dev/null
+++ b/pymusic-old/late_impl.h
@@ -0,0 +1,10 @@
+#include <mpi.h>
+
+#include "Python.h"
+
+PyObject* (*wrapIntracomm_ptr) (MPI_Comm comm) = 0;
+
+PyObject* wrapIntracomm (MPI_Comm comm)
+{
+  return (*wrapIntracomm_ptr) (comm);
+}
diff --git a/pymusic-old/music.pyx b/pymusic-old/music.pyx
new file mode 100644
index 0000000..46fcb04
--- /dev/null
+++ b/pymusic-old/music.pyx
@@ -0,0 +1,3 @@
+include "port.pxi"
+include "setup.pxi"
+include "runtime.pxi"
diff --git a/pymusic-old/port.pxd b/pymusic-old/port.pxd
new file mode 100644
index 0000000..7c8af77
--- /dev/null
+++ b/pymusic-old/port.pxd
@@ -0,0 +1,11 @@
+import sys
+
+cdef extern from "music/port.hh":
+    ctypedef struct cxx_EventOutputPort "MUSIC::EventOutputPort":
+        pass
+    ctypedef struct cxx_EventInputPort "MUSIC::EventInputPort":
+        pass
+
+# Local Variables:
+# mode: python
+# End:
diff --git a/pymusic-old/port.pxi b/pymusic-old/port.pxi
new file mode 100644
index 0000000..99362dc
--- /dev/null
+++ b/pymusic-old/port.pxi
@@ -0,0 +1,27 @@
+import sys
+
+from port cimport *
+
+cdef class EventOutputPort:
+    cdef cxx_EventOutputPort* cxx
+    def __cinit__(self):
+        pass
+
+cdef wrapEventOutputPort (cxx_EventOutputPort* port):
+    cdef EventOutputPort port_ = EventOutputPort ()
+    port_.cxx = port
+    return port_
+
+cdef class EventInputPort:
+    cdef cxx_EventInputPort* cxx
+    def __cinit__(self):
+        pass
+
+cdef wrapEventInputPort (cxx_EventInputPort* port):
+    cdef EventInputPort port_ = EventInputPort ()
+    port_.cxx = port
+    return port_
+
+# Local Variables:
+# mode: python
+# End:
diff --git a/pymusic-old/python_main.c b/pymusic-old/python_main.c
new file mode 100644
index 0000000..b5b09fd
--- /dev/null
+++ b/pymusic-old/python_main.c
@@ -0,0 +1,12 @@
+#include <Python.h>
+
+int
+main(int argc, char *argv[])
+{
+  Py_Initialize();
+  //PyRun_SimpleString("from time import time,ctime\n"
+  //                   "print 'Today is',ctime(time())\n");
+  Py_Main(argc, argv);
+  Py_Finalize();
+  return 0;
+}
diff --git a/pymusic-old/runtime.pxd b/pymusic-old/runtime.pxd
new file mode 100644
index 0000000..d68ef59
--- /dev/null
+++ b/pymusic-old/runtime.pxd
@@ -0,0 +1,20 @@
+from setup cimport *
+
+cdef extern from "music/runtime.hh":
+    ctypedef struct cxx_Runtime "MUSIC::Runtime":
+        
+        cxx_Intracomm communicator ()
+        
+        void tick ()
+        
+        double time ()
+        
+        void finalize ()
+        
+    cxx_Runtime *new_Runtime "new MUSIC::Runtime" (cxx_Setup* s, double h)
+    
+    void del_Runtime "delete" (cxx_Runtime *obj)
+
+# Local Variables:
+# mode: python
+# End:
diff --git a/pymusic-old/runtime.pxi b/pymusic-old/runtime.pxi
new file mode 100644
index 0000000..ec337a9
--- /dev/null
+++ b/pymusic-old/runtime.pxi
@@ -0,0 +1,28 @@
+from runtime cimport *
+
+cdef class Runtime:
+    cdef cxx_Runtime *cxx      # hold a C++ instance which we're wrapping
+    def __cinit__(self, Setup setup, h):
+        self.cxx = new_Runtime (setup.cxx, h)
+        # setup object is now deallocated
+        setup.cxx = NULL       # mark as deallocated
+
+    def __dealloc__(self):
+        del_Runtime (self.cxx)
+        
+    def communicator (self):
+        import music_late
+        return wrapIntracomm (intracommToC (self.cxx.communicator ()))
+
+    def tick (self):
+        self.cxx.tick ()
+
+    def time (self):
+        return self.cxx.time ()
+
+    def finalize (self):
+        self.cxx.finalize ()
+
+# Local Variables:
+# mode: python
+# End:
diff --git a/pymusic-old/setup.pxd b/pymusic-old/setup.pxd
new file mode 100644
index 0000000..e773eea
--- /dev/null
+++ b/pymusic-old/setup.pxd
@@ -0,0 +1,71 @@
+#
+#  This file is part of MUSIC.
+#  Copyright (C) 2009 INCF
+#
+#  MUSIC 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; either version 3 of the License, or
+#  (at your option) any later version.
+#
+#  MUSIC 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 should have received a copy of the GNU General Public License
+#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+from port cimport *
+
+from mpi4py.mpi_c cimport *
+
+cdef extern from "late_impl.h":
+    cdef wrapIntracomm (MPI_Comm comm)
+
+cdef extern from "music/setup.hh":
+    #
+    # This is the Python binding of the Setup object in the MUSIC API
+    #
+    # It is documented in section 4.3 of the MUSIC manual
+    #
+
+    # From mpi2py (which we cannot load here):
+    #ctypedef struct _mpi_comm_t
+    #ctypedef _mpi_comm_t* MPI_Comm
+    
+    ctypedef struct cxx_Intracomm "MPI::Intracomm":
+        MPI_Comm mpi_comm
+    
+    MPI_Comm intracommToC "(MPI_Comm)" (cxx_Intracomm comm)
+    
+    ctypedef struct cxx_Setup "MUSIC::Setup":
+
+        cxx_Intracomm communicator ()
+
+        #bool config (string var, string* result);
+
+        #bool config (string var, int* result);
+
+        #bool config (string var, double* result);
+
+        #ContInputPort* publishContInput (string identifier);
+
+        #ContOutputPort* publishContOutput (string identifier);
+
+        cxx_EventInputPort* publishEventInput (char* identifier)
+
+        cxx_EventOutputPort* publishEventOutput (char* identifier)
+
+        #MessageInputPort* publishMessageInput (string identifier);
+
+        #MessageOutputPort* publishMessageOutput (string identifier);
+
+    cxx_Setup *new_Setup "new MUSIC::Setup" (int argc, char** argv)
+    void del_Setup "delete" (cxx_Setup *obj)
+
+#cdef extern object PyMPIComm_New (MPI_Comm)
+    
+# Local Variables:
+# mode: python
+# End:
diff --git a/pymusic-old/setup.pxi b/pymusic-old/setup.pxi
new file mode 100644
index 0000000..aa88a6a
--- /dev/null
+++ b/pymusic-old/setup.pxi
@@ -0,0 +1,39 @@
+import sys
+
+from setup cimport *
+
+cdef class Setup:
+    cdef cxx_Setup* cxx      # hold a C++ instance which we're wrapping
+    def __cinit__(self, argv):
+        # Convert argv into C array
+        cdef int cxx_argc = 0
+        cdef char* storage[100] #*fixme*
+        cdef char** cxx_argv = storage
+        for arg in argv:
+            cxx_argv[cxx_argc] = arg
+            cxx_argc += 1
+            
+        self.cxx = new_Setup (cxx_argc, cxx_argv)
+
+        # Fill argv with C array
+        argv[:] = []
+        for i in range (0, cxx_argc):
+            argv.append (cxx_argv[i])
+            
+    def __dealloc__(self):
+        if self.cxx != NULL:
+            del_Setup (self.cxx)
+
+    def communicator (self):
+        import music_late
+        return wrapIntracomm (intracommToC (self.cxx.communicator ()))
+
+    def publishEventOutput (self, identifier):
+        return wrapEventOutputPort (self.cxx.publishEventOutput (identifier))
+
+    def publishEventInput (self, identifier):
+        return wrapEventInputPort (self.cxx.publishEventInput (identifier))
+
+# Local Variables:
+# mode: python
+# End:
diff --git a/pymusic-old/setup.py b/pymusic-old/setup.py
new file mode 100644
index 0000000..4e1c9cd
--- /dev/null
+++ b/pymusic-old/setup.py
@@ -0,0 +1,34 @@
+from distutils.core import setup
+from distutils.extension import Extension
+from Cython.Distutils import build_ext
+
+ext = Extension (
+    "music",                     # name of extension
+    ["music.pyx"],           # filename of our Cython source
+    language="c++",              # this causes Cython to create C++ source
+    include_dirs=['/usr/lib/openmpi/include',
+                  '/usr/local/lib/python/mpi4py/include',
+                  '/usr/local/include'],
+    library_dirs = ['/usr/lib/openmpi/lib',
+                    '/usr/local/lib'],
+    libraries=['music', 'mpi_cxx', 'mpi', 'open-rte', 'open-pal',
+               'dl', 'nsl', 'util', 'm'],
+    #extra_link_args=[...],       # if needed
+    )
+
+ext2 = Extension (
+    "music_late",
+    ["late.pyx"],
+    language = "c++",
+    include_dirs = ['/usr/lib/openmpi/include',
+                    '/usr/local/lib/python/mpi4py/include'],
+    extra_link_args = ['-Wl,-rpath=/home/mdj/sans/music/trunk/pymusic',
+                       'music.so']
+    )
+
+setup (name = "music",
+       version = "1.0",
+       description = 'Multi-Simulation Coordinator',
+       ext_modules = [ext, ext2],
+       cmdclass = {'build_ext': build_ext}
+       )
diff --git a/pymusic-old/test.py b/pymusic-old/test.py
new file mode 100644
index 0000000..36468f8
--- /dev/null
+++ b/pymusic-old/test.py
@@ -0,0 +1,8 @@
+#!/usr/local/bin/nrniv -python
+
+import sys
+import music
+
+s = music.Setup (sys.argv)
+p = s.publishEventOutput ("out")
+print p
diff --git a/pymusic/.gitignore b/pymusic/.gitignore
new file mode 100644
index 0000000..82b596d
--- /dev/null
+++ b/pymusic/.gitignore
@@ -0,0 +1,3 @@
+*.html
+/build/
+/setup.py
\ No newline at end of file
diff --git a/pymusic/Makefile.am b/pymusic/Makefile.am
new file mode 100644
index 0000000..098b6ad
--- /dev/null
+++ b/pymusic/Makefile.am
@@ -0,0 +1,53 @@
+
+EXTRA_DIST = setup.py.in pymusic.pyx pymusic.pxd music_c.h pybuffer.pyx pybuffer.pxd
+
+BUILT_SOURCES = pymusic.cpp pybuffer.cpp
+
+pybuffer.cpp: pybuffer.pyx pybuffer.pxd
+	cd $(top_srcdir)/pymusic; $(PYTHON) -c \
+	"from Cython.Build import cythonize; \
+	cythonize('pybuffer.pyx', verbose=1)"
+
+pymusic.cpp: pymusic.pyx pymusic.pxd
+	cd $(top_srcdir)/pymusic; $(PYTHON) -c \
+	"from Cython.Build import cythonize; \
+	cythonize('pymusic.pyx', verbose=1)"
+
+pkgpyexec_LTLIBRARIES = pymusic.la pybuffer.la
+pymusic_la_SOURCES= pymusic.cpp # main sources to link to
+pymusic_la_LDFLAGS = -shared -module -avoid-version -export-dynamic $(MPI_LDFLAGS)
+pybuffer_la_SOURCES= pybuffer.cpp # main sources to link to
+pybuffer_la_LDFLAGS = -shared -module -avoid-version -export-dynamic $(MPI_LDFLAGS)
+
+pymusic_la_CPPFLAGS = \
+	$(MPI_CPPFLAGS) \
+	$(PYMUSIC_CPPFLAGS) \
+	-I$(top_srcdir)/src
+
+pymusic_la_CXXFLAGS = \
+	$(PYMUSIC_CXXFLAGS) \
+	$(MPI_CXXFLAGS)
+
+pymusic_la_LIBADD = \
+	$(top_builddir)/src/libmusic.la \
+	$(top_builddir)/src/libmusic-c.la
+
+pybuffer_la_CPPFLAGS = \
+	$(MPI_CPPFLAGS) \
+	$(PYBUFFER_CPPFLAGS) \
+	-I$(top_srcdir)/src
+
+pybuffer_la_CXXFLAGS = \
+	$(PYBUFFER_CXXFLAGS) \
+	$(MPI_CXXFLAGS)
+
+install-exec-hook:
+	$(PYTHON) setup.py build \
+	  --build-base=$(abs_builddir)/build install \
+	  --prefix=$(DESTDIR)$(prefix) \
+	  --install-lib=$(DESTDIR)$(pyexecdir) \
+	  --install-scripts=$(DESTDIR)$(bindir) \
+	  --install-data=$(DESTDIR)$(pkgdatadir)
+
+clean-local:
+	-rm -rf $(abs_builddir)/build
diff --git a/pymusic/examples/event.music b/pymusic/examples/event.music
new file mode 100644
index 0000000..9d1e673
--- /dev/null
+++ b/pymusic/examples/event.music
@@ -0,0 +1,14 @@
+np=2
+stoptime=5.0
+timestep=0.5
+errorAt=-1
+
+buffer=1
+events=50
+
+[from]
+  binary=./eventsource.py
+
+[to]
+  binary=./eventlogger.py
+  from.out -> to.in [10]
diff --git a/pymusic/examples/eventlogger.py b/pymusic/examples/eventlogger.py
new file mode 100755
index 0000000..1b21a70
--- /dev/null
+++ b/pymusic/examples/eventlogger.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+
+import music
+import sys
+from itertools import takewhile
+
+setup = music.Setup()
+stoptime = setup.config("stoptime")
+timestep = setup.config("timestep")
+buf = setup.config("buffer")
+
+errorAt = setup.config("errorAt")
+if errorAt < 0: errorAt = None
+
+comm = setup.comm
+rank = comm.Get_rank()
+size = comm.Get_size()
+
+inp = setup.publishEventInput("in")
+
+width = inp.width()
+local = width // size
+rest = width % size
+firstId = rank * local
+
+# distribute the rest:
+firstId += min(rank, rest)
+if rank < rest: local += 1
+
+def eventerr(d):
+    if errorAt is None: return
+    if d >= errorAt: raise RuntimeError("Hey")
+
+time = None
+def eventfunc(d, t, i):
+    eventerr(d)
+    sys.stderr.write("Receive rank {}: Event ({}, {}) at {}\n".
+                     format(rank, i, d, time))
+
+inp.map(eventfunc, 
+        music.Index.GLOBAL, 
+        base=firstId, 
+        size=local,
+        maxBuffered=buf)
+
+runtime = music.Runtime(setup, timestep)
+times = takewhile(lambda t: t <= stoptime, runtime)
+for time in times:
+    pass
diff --git a/pymusic/examples/eventsource.py b/pymusic/examples/eventsource.py
new file mode 100755
index 0000000..9d0800b
--- /dev/null
+++ b/pymusic/examples/eventsource.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+
+import music
+from itertools import groupby, ifilter, takewhile
+import sys
+
+setup = music.Setup()
+stoptime = setup.config("stoptime")
+timestep = setup.config("timestep")
+buf = setup.config("buffer")
+events = setup.config("events")
+
+comm = setup.comm
+rank = comm.Get_rank()
+size = comm.Get_size()
+
+out = setup.publishEventOutput("out")
+
+width = out.width()
+local = width // size
+rest = width % size
+firstId = rank * local
+
+# distribute the rest:
+firstId += min(rank, rest)
+if rank < rest: local += 1
+
+out.map(music.Index.GLOBAL,
+        base=firstId,
+        size=local,
+        maxBuffered=buf)
+
+eventgen = ((firstId + i % local, i * stoptime / events)
+            for i in xrange(events)) # index, time
+steps = groupby(eventgen, lambda (i , t): int(t/timestep))
+def step(): return next(steps, (None, None))
+
+runtime = setup.runtime(timestep)
+times = takewhile(lambda t: t < stoptime, runtime)
+nextStep, nextEvents = step()
+for t in times:
+    if int(t/timestep) != nextStep: continue
+
+    for index, when in nextEvents:
+        sys.stderr.write("Insert rank {}: Event ({}, {}) at {}\n".
+                         format(rank, index, when, t))
+        out.insertEvent(when, index, music.Index.GLOBAL)
+
+    nextStep, nextEvents = step()
diff --git a/pymusic/examples/helloworld.music b/pymusic/examples/helloworld.music
new file mode 100644
index 0000000..0c95205
--- /dev/null
+++ b/pymusic/examples/helloworld.music
@@ -0,0 +1,8 @@
+np=2
+stoptime=5.0
+timestep=0.5
+[from]
+  binary=./senders.py
+[to]
+  binary=./receivers.py
+  from.out -> to.in
diff --git a/pymusic/examples/message.music b/pymusic/examples/message.music
new file mode 100644
index 0000000..5213035
--- /dev/null
+++ b/pymusic/examples/message.music
@@ -0,0 +1,15 @@
+np=2
+stoptime=5.0
+timestep=0.5
+pickled=1
+
+buffer=1
+events=50
+errorAt=-1
+
+[from]
+  binary=./messagesource.py
+
+[to]
+  binary=./messagelogger.py
+  from.out -> to.in
diff --git a/pymusic/examples/message.py b/pymusic/examples/message.py
new file mode 100644
index 0000000..5adfe5d
--- /dev/null
+++ b/pymusic/examples/message.py
@@ -0,0 +1,17 @@
+######################################################################
+
+class Msg(object):
+    def __init__(self, rank, step, time, when):
+        self.rank = rank
+        self.step = step
+        self.time = time
+        self.when = when
+
+    def __str__(self):
+        return "{}, {}, {}, {}". \
+            format(self.rank,
+                   self.step,
+                   self.time,
+                   self.when)
+
+######################################################################
diff --git a/pymusic/examples/messagelogger.py b/pymusic/examples/messagelogger.py
new file mode 100755
index 0000000..11139d2
--- /dev/null
+++ b/pymusic/examples/messagelogger.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+
+import music
+import sys
+from itertools import takewhile
+
+setup = music.Setup()
+stoptime = setup.config("stoptime")
+timestep = setup.config("timestep")
+buf = setup.config("buffer")
+pickled = setup.config("pickled") != 0
+
+errorAt = setup.config("errorAt")
+if errorAt < 0: errorAt = None
+
+comm = setup.comm
+rank = comm.Get_rank()
+size = comm.Get_size()
+
+def eventerr(d):
+    if errorAt is None: return
+    if d >= errorAt: raise RuntimeError("Hey")
+
+time = None
+def msgfunc(d, msg):
+    eventerr(d)
+    sys.stderr.write(
+        "Receive rank {}: {} ({}) at {}\n".
+        format(rank, type(msg), msg, d))
+
+inp = setup.publishMessageInput("in")
+inp.map(msgfunc, maxBuffered=buf, pickled=pickled)
+
+runtime = setup.runtime(timestep)
+times = takewhile(lambda t: t <= stoptime, runtime)
+for time in times:
+    pass
diff --git a/pymusic/examples/messagesource.py b/pymusic/examples/messagesource.py
new file mode 100755
index 0000000..39b0de9
--- /dev/null
+++ b/pymusic/examples/messagesource.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+
+import music
+from itertools import groupby, takewhile
+from message import Msg
+
+setup = music.Setup()
+stoptime = setup.config("stoptime")
+timestep = setup.config("timestep")
+buf = setup.config("buffer")
+events = setup.config("events")
+pickled = setup.config("pickled") != 0
+
+comm = setup.comm
+rank = comm.Get_rank()
+size = comm.Get_size()
+
+out = setup.publishMessageOutput("out")
+out.map(maxBuffered=buf, pickled=pickled)
+
+eventgen = (i * stoptime / events
+            for i in xrange(events)
+            if i % size == rank)
+steps = groupby(eventgen, lambda t: int(t/timestep))
+def step(): return next(steps, (None, None))
+
+runtime = setup.runtime(timestep)
+times = takewhile(lambda t: t < stoptime, runtime)
+nextStep, nextEvents = step()
+for t in times:
+    if int(t/timestep) != nextStep: continue
+
+    for when in nextEvents:
+        msg = Msg(rank, nextStep, t, when)
+        if not pickled: msg = str(msg)
+        out.insertMessage(when, msg)
+
+    nextStep, nextEvents = step()
diff --git a/pymusic/examples/receivers.py b/pymusic/examples/receivers.py
new file mode 100755
index 0000000..a95af65
--- /dev/null
+++ b/pymusic/examples/receivers.py
@@ -0,0 +1,29 @@
+#! /usr/bin/python
+
+import music
+
+import sys
+import numpy
+from itertools import takewhile, dropwhile
+
+setup = music.Setup()
+stoptime = setup.config("stoptime")
+timestep = setup.config("timestep")
+
+comm = setup.comm
+rank = comm.Get_rank()
+
+pin = setup.publishContInput("in")
+data = numpy.array([-2], dtype=numpy.int)
+pin.map(data, base=rank)
+
+runtime = setup.runtime(timestep)
+mintime = timestep
+maxtime = stoptime+timestep
+start = dropwhile(lambda t: t < mintime, runtime)
+times = takewhile(lambda t: t < maxtime, start)
+for time in times:
+    srank = data[0]
+    sys.stdout.write(
+        "t={}\treceiver {}: received Hello from sender {}\n".
+        format(time, rank, srank))
diff --git a/pymusic/examples/senders.py b/pymusic/examples/senders.py
new file mode 100755
index 0000000..256b4a2
--- /dev/null
+++ b/pymusic/examples/senders.py
@@ -0,0 +1,24 @@
+#! /usr/bin/python
+
+import music
+
+import sys
+import numpy
+from itertools import takewhile
+
+setup = music.Setup()
+stoptime = setup.config("stoptime")
+timestep = setup.config("timestep")
+
+comm = setup.comm
+rank = comm.Get_rank()
+
+out = setup.publishContOutput("out")
+data = numpy.array([-1], dtype=numpy.int)
+out.map(data, base=rank)
+
+runtime = setup.runtime(timestep)
+times = takewhile(lambda t: t < stoptime, runtime)
+for time in times:
+    data[0] = rank
+    sys.stdout.write("t={}\tsender {}: Hello!\n".format(time, rank))
diff --git a/pymusic/examples/test.music b/pymusic/examples/test.music
new file mode 100644
index 0000000..5dbea17
--- /dev/null
+++ b/pymusic/examples/test.music
@@ -0,0 +1,13 @@
+np = 2
+stoptime = 5.0
+timestep = 0.5
+
+buffer = 1
+events = 20
+
+[from]
+  binary = ./testsource.py
+
+[to]
+  binary = ./testsink.py
+  from.out -> to.in [10]
diff --git a/pymusic/examples/testsink.py b/pymusic/examples/testsink.py
new file mode 100755
index 0000000..ddb6cc8
--- /dev/null
+++ b/pymusic/examples/testsink.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+
+import music
+import sys
+from itertools import takewhile
+
+setup = music.Setup()
+stoptime = setup.config("stoptime")
+timestep = setup.config("timestep")
+buf = setup.config("buffer")
+
+comm = setup.comm
+rank = comm.Get_rank()
+size = comm.Get_size()
+
+inp = setup.publishEventInput("in")
+
+width = inp.width()
+local = width // size
+rest = width % size
+firstId = rank * local
+
+# distribute the rest:
+firstId += min(rank, rest)
+if rank < rest: local += 1
+
+def eventerr(d):
+    if errorAt is None: return
+    if d >= errorAt: raise RuntimeError("Hey")
+
+time = None
+def eventfunc(d, t, i):
+    sys.stderr.write(
+        "Receive rank {}: val={}, ind={}, type={}\n".
+        format(rank, d, i, music.Index.tostr(t)))
+
+inp.map(eventfunc, 
+        music.Index.GLOBAL, 
+        base=firstId, 
+        size=local,
+        maxBuffered=buf)
+
+runtime = music.Runtime(setup, timestep)
+times = takewhile(lambda t: t <= stoptime, runtime)
+for time in times:
+    pass
diff --git a/pymusic/examples/testsource.py b/pymusic/examples/testsource.py
new file mode 100755
index 0000000..87b49aa
--- /dev/null
+++ b/pymusic/examples/testsource.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+
+import music
+from itertools import groupby, ifilter, takewhile
+import sys
+
+setup = music.Setup()
+stoptime = setup.config("stoptime")
+timestep = setup.config("timestep")
+buf = setup.config("buffer")
+events = setup.config("events")
+
+comm = setup.comm
+rank = comm.Get_rank()
+size = comm.Get_size()
+
+out = setup.publishEventOutput("out")
+
+width = out.width()
+local = width // size
+rest = width % size
+firstId = rank * local
+
+# distribute the rest:
+firstId += min(rank, rest)
+if rank < rest: local += 1
+
+index = music.Index.LOCAL
+
+if index == music.Index.LOCAL:
+    def mapout(i): return i
+else:
+    def mapout(i): return i + firstId
+
+out.map(index,
+        base=firstId,
+        size=local,
+        maxBuffered=buf)
+
+eventgen = ((mapout(i % local), i * stoptime / events)
+            for i in xrange(events)) # index, time
+steps = groupby(eventgen, lambda (i , t): int(t/timestep))
+def step(): return next(steps, (None, None))
+
+runtime = setup.runtime(timestep)
+times = takewhile(lambda t: t < stoptime, runtime)
+nextStep, nextEvents = step()
+for t in times:
+    if int(t/timestep) != nextStep: continue
+
+    for i, when in nextEvents:
+        sys.stderr.write("Insert rank {}: val={}, type={}, ind={}\n".
+                         format(rank, when, i, music.Index.tostr(index)))
+        out.insertEvent(when, i, index)
+
+    nextStep, nextEvents = step()
diff --git a/pymusic/music/__init__.py b/pymusic/music/__init__.py
new file mode 100644
index 0000000..65b6644
--- /dev/null
+++ b/pymusic/music/__init__.py
@@ -0,0 +1,29 @@
+############ 
+#https://svn.boost.org/trac/boost/ticket/6580
+#https://github.com/salilab/imp/issues/732
+# this should be in the __init__.py
+#
+# How to check for openmpi?
+#
+import sys
+def setrc():
+    import mpi4py.rc
+    mpi4py.rc.initialize = False
+    mpi4py.rc.finalize = False
+
+if sys.platform == 'linux2':
+    import DLFCN as dl
+    flags = sys.getdlopenflags()
+    sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)
+
+    setrc()
+    from pymusic import *
+
+    sys.setdlopenflags(flags)
+else:
+    setrc()
+    from pymusic import *
+
+#import DLFCN as dl
+#import sys
+#sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)
diff --git a/pymusic/music/music_c.h b/pymusic/music/music_c.h
new file mode 100644
index 0000000..3b4d10a
--- /dev/null
+++ b/pymusic/music/music_c.h
@@ -0,0 +1,178 @@
+#ifndef MUSIC_C_H
+#define MUSIC_C_H
+
+#include <Python.h>
+
+#include <mpi.h>
+#include "music/setup.hh"
+#include "music/runtime.hh"
+#include "music/index_map.hh"
+#include "music/event.hh"
+#include "music/message.hh"
+#include "music/configuration.hh"
+
+#include <iostream>
+#include <string>
+
+namespace MUSIC {
+  using namespace std;
+
+  inline MPI_Comm communicator(MUSIC::Setup* s) {
+    return (MPI_Comm) s->communicator();
+  }
+
+  inline MPI_Comm communicator(MUSIC::Runtime* r) {
+    return (MPI_Comm) r->communicator();
+  }
+
+  inline int toint(MUSIC::GlobalIndex i) {
+    return i;
+  }
+
+  inline int toint(MUSIC::LocalIndex i) {
+    return i;
+  }
+
+  static bool pythonError;
+  static PyObject* etype;
+  static PyObject* evalue;
+  static PyObject* etraceback;
+
+  bool tick(Runtime* ptr) {
+    ptr->tick();
+    if (! pythonError) return true;
+
+    pythonError = false;
+    PyErr_Restore(etype, evalue, etraceback);
+    return false;
+  }
+
+  bool EventCallback(PyObject* func,
+		     double d,
+		     Index::Type t,
+		     int index);
+
+  class EventHandler { // All this just to insert a virtual d
+  public:
+    PyObject* const func;
+
+    EventHandler(PyObject* func): func(func) {}
+    virtual ~EventHandler() {}
+    inline void callback(double d, Index::Type t, int i) {
+      if (pythonError) return;
+      if (EventCallback(func, d, t, i)) return;
+
+      pythonError = true;
+      PyErr_Fetch(&etype, &evalue, &etraceback);
+    }
+  };
+
+
+  class EHLocal: public EventHandler,
+		 public EventHandlerLocalIndex {
+  public:
+    EHLocal(PyObject* func): EventHandler(func) {};
+    void operator() (double d, LocalIndex i) {
+      callback(d, Index::LOCAL, i);
+    }
+  };
+
+  class EHGlobal: public EventHandler, public EventHandlerGlobalIndex {
+  public:
+    EHGlobal(PyObject* func): EventHandler(func) {};
+    void operator() (double d, GlobalIndex i) {
+      callback(d, Index::GLOBAL, i);
+    }
+  };
+
+  inline
+  EventHandlerPtr getEventHandlerPtr(Index::Type t,
+				     EventHandler* eh) {
+    return (t == Index::GLOBAL)
+      ? EventHandlerPtr((EHGlobal*) eh)
+      : EventHandlerPtr((EHLocal*) eh);
+  }
+
+  bool MessageCallback(PyObject* func,
+		       double t,
+		       void* msg,
+		       size_t size,
+		       bool pickled);
+
+  class MHandler: public MessageHandler {
+  public:
+    PyObject* const func;
+    const bool pickled;
+
+    MHandler(PyObject* func, bool pickled):
+      func(func), pickled(pickled) {}
+    void operator () (double t, void* msg, size_t size) {
+      if (pythonError) return;
+      if (MessageCallback(func, t, msg, size, pickled)) return;
+
+      pythonError = true;
+      PyErr_Fetch(&etype, &evalue, &etraceback);
+    }
+  };
+
+  class Implementer {
+  public:
+    static inline
+    void mapImpl(ContInputPort* p,
+		 DataMap* d,
+		 double v,
+		 int i,
+		 bool b) {
+      p->ContInputPort::mapImpl(d, v, i, b);
+    }
+
+    static inline
+    void mapImpl(ContOutputPort* p,
+		 DataMap* d,
+		 int i) {
+      p->ContOutputPort::mapImpl(d, i);
+    }
+
+    static inline
+    void mapImpl(EventInputPort* p,
+		 IndexMap* m,
+		 Index::Type t,
+		 EventHandlerPtr e,
+		 double d,
+		 int i) {
+      p->EventInputPort::mapImpl(m, t, e, d, i);
+    }
+
+    static inline
+    void mapImpl(EventOutputPort* p,
+		 IndexMap* m,
+		 Index::Type t,
+		 int i) {
+      p->EventOutputPort::mapImpl(m, t, i);
+    }
+
+    static inline
+    void insertEventImpl(EventOutputPort* p,
+			 double d,
+			 int i) {
+      p->EventOutputPort::insertEventImpl(d, i);
+    }
+    static inline
+    void mapImpl(MessageInputPort* p,
+		 MessageHandler* handler,
+		 double accLatency,
+		 int maxBuffered) {
+      p->MessageInputPort::mapImpl(handler,
+				   accLatency,
+				   maxBuffered);
+    }
+
+    static inline
+    void mapImpl(MessageOutputPort* p,
+		 int maxBuffered) {
+      p->MessageOutputPort::mapImpl(maxBuffered);
+    }
+  };
+}
+
+#endif // MUSIC_C_H
diff --git a/pymusic/music/pybuffer.pxd b/pymusic/music/pybuffer.pxd
new file mode 120000
index 0000000..3d0446c
--- /dev/null
+++ b/pymusic/music/pybuffer.pxd
@@ -0,0 +1 @@
+../pybuffer.pxd
\ No newline at end of file
diff --git a/pymusic/music/pymusic.pxd b/pymusic/music/pymusic.pxd
new file mode 120000
index 0000000..b5ce7a3
--- /dev/null
+++ b/pymusic/music/pymusic.pxd
@@ -0,0 +1 @@
+../pymusic.pxd
\ No newline at end of file
diff --git a/pymusic/music/pymusic_c.h b/pymusic/music/pymusic_c.h
new file mode 100644
index 0000000..2721692
--- /dev/null
+++ b/pymusic/music/pymusic_c.h
@@ -0,0 +1,12 @@
+#ifndef PYMUSIC_C_H
+#define PYMUSIC_C_H
+
+#include "Python.h"
+
+#if PY_MAJOR_VERSION >= 3
+#define PyUnicodeString_FromString  PyUnicode_FromString
+#else
+#define PyUnicodeString_FromString  PyString_FromString
+#endif
+
+#endif // PYMUSIC_C_H
diff --git a/pymusic/pybuffer.cpp b/pymusic/pybuffer.cpp
new file mode 100644
index 0000000..18b26cc
--- /dev/null
+++ b/pymusic/pybuffer.cpp
@@ -0,0 +1,3564 @@
+/* Generated by Cython 0.20 on Thu Oct 30 17:05:56 2014 */
+
+#define PY_SSIZE_T_CLEAN
+#ifndef CYTHON_USE_PYLONG_INTERNALS
+#ifdef PYLONG_BITS_IN_DIGIT
+#define CYTHON_USE_PYLONG_INTERNALS 0
+#else
+#include "pyconfig.h"
+#ifdef PYLONG_BITS_IN_DIGIT
+#define CYTHON_USE_PYLONG_INTERNALS 1
+#else
+#define CYTHON_USE_PYLONG_INTERNALS 0
+#endif
+#endif
+#endif
+#include "Python.h"
+#ifndef Py_PYTHON_H
+    #error Python headers needed to compile C extensions, please install development version of Python.
+#elif PY_VERSION_HEX < 0x02040000
+    #error Cython requires Python 2.4+.
+#else
+#define CYTHON_ABI "0_20"
+#include <stddef.h> /* For offsetof */
+#ifndef offsetof
+#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
+#endif
+#if !defined(WIN32) && !defined(MS_WINDOWS)
+  #ifndef __stdcall
+    #define __stdcall
+  #endif
+  #ifndef __cdecl
+    #define __cdecl
+  #endif
+  #ifndef __fastcall
+    #define __fastcall
+  #endif
+#endif
+#ifndef DL_IMPORT
+  #define DL_IMPORT(t) t
+#endif
+#ifndef DL_EXPORT
+  #define DL_EXPORT(t) t
+#endif
+#ifndef PY_LONG_LONG
+  #define PY_LONG_LONG LONG_LONG
+#endif
+#ifndef Py_HUGE_VAL
+  #define Py_HUGE_VAL HUGE_VAL
+#endif
+#ifdef PYPY_VERSION
+#define CYTHON_COMPILING_IN_PYPY 1
+#define CYTHON_COMPILING_IN_CPYTHON 0
+#else
+#define CYTHON_COMPILING_IN_PYPY 0
+#define CYTHON_COMPILING_IN_CPYTHON 1
+#endif
+#if CYTHON_COMPILING_IN_PYPY
+#define Py_OptimizeFlag 0
+#endif
+#if PY_VERSION_HEX < 0x02050000
+  typedef int Py_ssize_t;
+  #define PY_SSIZE_T_MAX INT_MAX
+  #define PY_SSIZE_T_MIN INT_MIN
+  #define PY_FORMAT_SIZE_T ""
+  #define CYTHON_FORMAT_SSIZE_T ""
+  #define PyInt_FromSsize_t(z) PyInt_FromLong(z)
+  #define PyInt_AsSsize_t(o)   __Pyx_PyInt_As_int(o)
+  #define PyNumber_Index(o)    ((PyNumber_Check(o) && !PyFloat_Check(o)) ? PyNumber_Int(o) : \
+                                (PyErr_Format(PyExc_TypeError, \
+                                              "expected index value, got %.200s", Py_TYPE(o)->tp_name), \
+                                 (PyObject*)0))
+  #define __Pyx_PyIndex_Check(o) (PyNumber_Check(o) && !PyFloat_Check(o) && \
+                                  !PyComplex_Check(o))
+  #define PyIndex_Check __Pyx_PyIndex_Check
+  #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message)
+  #define __PYX_BUILD_PY_SSIZE_T "i"
+#else
+  #define __PYX_BUILD_PY_SSIZE_T "n"
+  #define CYTHON_FORMAT_SSIZE_T "z"
+  #define __Pyx_PyIndex_Check PyIndex_Check
+#endif
+#if PY_VERSION_HEX < 0x02060000
+  #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt)
+  #define Py_TYPE(ob)   (((PyObject*)(ob))->ob_type)
+  #define Py_SIZE(ob)   (((PyVarObject*)(ob))->ob_size)
+  #define PyVarObject_HEAD_INIT(type, size) \
+          PyObject_HEAD_INIT(type) size,
+  #define PyType_Modified(t)
+  typedef struct {
+     void *buf;
+     PyObject *obj;
+     Py_ssize_t len;
+     Py_ssize_t itemsize;
+     int readonly;
+     int ndim;
+     char *format;
+     Py_ssize_t *shape;
+     Py_ssize_t *strides;
+     Py_ssize_t *suboffsets;
+     void *internal;
+  } Py_buffer;
+  #define PyBUF_SIMPLE 0
+  #define PyBUF_WRITABLE 0x0001
+  #define PyBUF_FORMAT 0x0004
+  #define PyBUF_ND 0x0008
+  #define PyBUF_STRIDES (0x0010 | PyBUF_ND)
+  #define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES)
+  #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
+  #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
+  #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
+  #define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE)
+  #define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE)
+  typedef int (*getbufferproc)(PyObject *, Py_buffer *, int);
+  typedef void (*releasebufferproc)(PyObject *, Py_buffer *);
+#endif
+#if PY_MAJOR_VERSION < 3
+  #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
+  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
+          PyCode_New(a, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
+  #define __Pyx_DefaultClassType PyClass_Type
+#else
+  #define __Pyx_BUILTIN_MODULE_NAME "builtins"
+  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
+          PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
+  #define __Pyx_DefaultClassType PyType_Type
+#endif
+#if PY_VERSION_HEX < 0x02060000
+  #define PyUnicode_FromString(s) PyUnicode_Decode(s, strlen(s), "UTF-8", "strict")
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define Py_TPFLAGS_CHECKTYPES 0
+  #define Py_TPFLAGS_HAVE_INDEX 0
+#endif
+#if (PY_VERSION_HEX < 0x02060000) || (PY_MAJOR_VERSION >= 3)
+  #define Py_TPFLAGS_HAVE_NEWBUFFER 0
+#endif
+#if PY_VERSION_HEX < 0x02060000
+  #define Py_TPFLAGS_HAVE_VERSION_TAG 0
+#endif
+#if PY_VERSION_HEX < 0x02060000 && !defined(Py_TPFLAGS_IS_ABSTRACT)
+  #define Py_TPFLAGS_IS_ABSTRACT 0
+#endif
+#if PY_VERSION_HEX < 0x030400a1 && !defined(Py_TPFLAGS_HAVE_FINALIZE)
+  #define Py_TPFLAGS_HAVE_FINALIZE 0
+#endif
+#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND)
+  #define CYTHON_PEP393_ENABLED 1
+  #define __Pyx_PyUnicode_READY(op)       (likely(PyUnicode_IS_READY(op)) ? \
+                                              0 : _PyUnicode_Ready((PyObject *)(op)))
+  #define __Pyx_PyUnicode_GET_LENGTH(u)   PyUnicode_GET_LENGTH(u)
+  #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
+  #define __Pyx_PyUnicode_KIND(u)         PyUnicode_KIND(u)
+  #define __Pyx_PyUnicode_DATA(u)         PyUnicode_DATA(u)
+  #define __Pyx_PyUnicode_READ(k, d, i)   PyUnicode_READ(k, d, i)
+#else
+  #define CYTHON_PEP393_ENABLED 0
+  #define __Pyx_PyUnicode_READY(op)       (0)
+  #define __Pyx_PyUnicode_GET_LENGTH(u)   PyUnicode_GET_SIZE(u)
+  #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
+  #define __Pyx_PyUnicode_KIND(u)         (sizeof(Py_UNICODE))
+  #define __Pyx_PyUnicode_DATA(u)         ((void*)PyUnicode_AS_UNICODE(u))
+  #define __Pyx_PyUnicode_READ(k, d, i)   ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i]))
+#endif
+#define __Pyx_PyString_FormatSafe(a, b)  ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b))
+#define __Pyx_PyUnicode_FormatSafe(a, b)  ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
+#define __Pyx_PyUnicode_Concat(a, b)  ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \
+    PyNumber_Add(a, b) : PyUnicode_Concat(a, b))
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyString_Format(a, b)  PyUnicode_Format(a, b)
+#else
+  #define __Pyx_PyString_Format(a, b)  PyString_Format(a, b)
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define PyBaseString_Type            PyUnicode_Type
+  #define PyStringObject               PyUnicodeObject
+  #define PyString_Type                PyUnicode_Type
+  #define PyString_Check               PyUnicode_Check
+  #define PyString_CheckExact          PyUnicode_CheckExact
+#endif
+#if PY_VERSION_HEX < 0x02060000
+  #define PyBytesObject                PyStringObject
+  #define PyBytes_Type                 PyString_Type
+  #define PyBytes_Check                PyString_Check
+  #define PyBytes_CheckExact           PyString_CheckExact
+  #define PyBytes_FromString           PyString_FromString
+  #define PyBytes_FromStringAndSize    PyString_FromStringAndSize
+  #define PyBytes_FromFormat           PyString_FromFormat
+  #define PyBytes_DecodeEscape         PyString_DecodeEscape
+  #define PyBytes_AsString             PyString_AsString
+  #define PyBytes_AsStringAndSize      PyString_AsStringAndSize
+  #define PyBytes_Size                 PyString_Size
+  #define PyBytes_AS_STRING            PyString_AS_STRING
+  #define PyBytes_GET_SIZE             PyString_GET_SIZE
+  #define PyBytes_Repr                 PyString_Repr
+  #define PyBytes_Concat               PyString_Concat
+  #define PyBytes_ConcatAndDel         PyString_ConcatAndDel
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj)
+  #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj)
+#else
+  #define __Pyx_PyBaseString_Check(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj) || \
+                                         PyString_Check(obj) || PyUnicode_Check(obj))
+  #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj))
+#endif
+#if PY_VERSION_HEX < 0x02060000
+  #define PySet_Check(obj)             PyObject_TypeCheck(obj, &PySet_Type)
+  #define PyFrozenSet_Check(obj)       PyObject_TypeCheck(obj, &PyFrozenSet_Type)
+#endif
+#ifndef PySet_CheckExact
+  #define PySet_CheckExact(obj)        (Py_TYPE(obj) == &PySet_Type)
+#endif
+#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
+#if PY_MAJOR_VERSION >= 3
+  #define PyIntObject                  PyLongObject
+  #define PyInt_Type                   PyLong_Type
+  #define PyInt_Check(op)              PyLong_Check(op)
+  #define PyInt_CheckExact(op)         PyLong_CheckExact(op)
+  #define PyInt_FromString             PyLong_FromString
+  #define PyInt_FromUnicode            PyLong_FromUnicode
+  #define PyInt_FromLong               PyLong_FromLong
+  #define PyInt_FromSize_t             PyLong_FromSize_t
+  #define PyInt_FromSsize_t            PyLong_FromSsize_t
+  #define PyInt_AsLong                 PyLong_AsLong
+  #define PyInt_AS_LONG                PyLong_AS_LONG
+  #define PyInt_AsSsize_t              PyLong_AsSsize_t
+  #define PyInt_AsUnsignedLongMask     PyLong_AsUnsignedLongMask
+  #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
+  #define PyNumber_Int                 PyNumber_Long
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define PyBoolObject                 PyLongObject
+#endif
+#if PY_VERSION_HEX < 0x03020000
+  typedef long Py_hash_t;
+  #define __Pyx_PyInt_FromHash_t PyInt_FromLong
+  #define __Pyx_PyInt_AsHash_t   PyInt_AsLong
+#else
+  #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t
+  #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
+#endif
+#if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300)
+  #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b)
+  #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value)
+  #define __Pyx_PySequence_DelSlice(obj, a, b) PySequence_DelSlice(obj, a, b)
+#else
+  #define __Pyx_PySequence_GetSlice(obj, a, b) (unlikely(!(obj)) ? \
+        (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), (PyObject*)0) : \
+        (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_GetSlice(obj, a, b)) : \
+            (PyErr_Format(PyExc_TypeError, "'%.200s' object is unsliceable", (obj)->ob_type->tp_name), (PyObject*)0)))
+  #define __Pyx_PySequence_SetSlice(obj, a, b, value) (unlikely(!(obj)) ? \
+        (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \
+        (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_SetSlice(obj, a, b, value)) : \
+            (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice assignment", (obj)->ob_type->tp_name), -1)))
+  #define __Pyx_PySequence_DelSlice(obj, a, b) (unlikely(!(obj)) ? \
+        (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \
+        (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_DelSlice(obj, a, b)) : \
+            (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice deletion", (obj)->ob_type->tp_name), -1)))
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func))
+#endif
+#if PY_VERSION_HEX < 0x02050000
+  #define __Pyx_GetAttrString(o,n)   PyObject_GetAttrString((o),((char *)(n)))
+  #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),((char *)(n)),(a))
+  #define __Pyx_DelAttrString(o,n)   PyObject_DelAttrString((o),((char *)(n)))
+#else
+  #define __Pyx_GetAttrString(o,n)   PyObject_GetAttrString((o),(n))
+  #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),(n),(a))
+  #define __Pyx_DelAttrString(o,n)   PyObject_DelAttrString((o),(n))
+#endif
+#if PY_VERSION_HEX < 0x02050000
+  #define __Pyx_NAMESTR(n) ((char *)(n))
+  #define __Pyx_DOCSTR(n)  ((char *)(n))
+#else
+  #define __Pyx_NAMESTR(n) (n)
+  #define __Pyx_DOCSTR(n)  (n)
+#endif
+#ifndef CYTHON_INLINE
+  #if defined(__GNUC__)
+    #define CYTHON_INLINE __inline__
+  #elif defined(_MSC_VER)
+    #define CYTHON_INLINE __inline
+  #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+    #define CYTHON_INLINE inline
+  #else
+    #define CYTHON_INLINE
+  #endif
+#endif
+#ifndef CYTHON_RESTRICT
+  #if defined(__GNUC__)
+    #define CYTHON_RESTRICT __restrict__
+  #elif defined(_MSC_VER) && _MSC_VER >= 1400
+    #define CYTHON_RESTRICT __restrict
+  #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+    #define CYTHON_RESTRICT restrict
+  #else
+    #define CYTHON_RESTRICT
+  #endif
+#endif
+#ifdef NAN
+#define __PYX_NAN() ((float) NAN)
+#else
+static CYTHON_INLINE float __PYX_NAN() {
+  /* Initialize NaN. The sign is irrelevant, an exponent with all bits 1 and
+   a nonzero mantissa means NaN. If the first bit in the mantissa is 1, it is
+   a quiet NaN. */
+  float value;
+  memset(&value, 0xFF, sizeof(value));
+  return value;
+}
+#endif
+
+
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#else
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_Divide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceDivide(x,y)
+#endif
+
+#ifndef __PYX_EXTERN_C
+  #ifdef __cplusplus
+    #define __PYX_EXTERN_C extern "C"
+  #else
+    #define __PYX_EXTERN_C extern
+  #endif
+#endif
+
+#if defined(WIN32) || defined(MS_WINDOWS)
+#define _USE_MATH_DEFINES
+#endif
+#include <math.h>
+#define __PYX_HAVE__pybuffer
+#define __PYX_HAVE_API__pybuffer
+#include "mpi.h"
+#include "music/pymusic_c.h"
+#include "string.h"
+#include "stdlib.h"
+#ifdef _OPENMP
+#include <omp.h>
+#endif /* _OPENMP */
+
+#ifdef PYREX_WITHOUT_ASSERTIONS
+#define CYTHON_WITHOUT_ASSERTIONS
+#endif
+
+#ifndef CYTHON_UNUSED
+# if defined(__GNUC__)
+#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#     define CYTHON_UNUSED __attribute__ ((__unused__))
+#   else
+#     define CYTHON_UNUSED
+#   endif
+# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
+#   define CYTHON_UNUSED __attribute__ ((__unused__))
+# else
+#   define CYTHON_UNUSED
+# endif
+#endif
+typedef struct {PyObject **p; char *s; const Py_ssize_t n; const char* encoding;
+                const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/
+
+#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
+#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0
+#define __PYX_DEFAULT_STRING_ENCODING ""
+#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
+#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
+#define __Pyx_fits_Py_ssize_t(v, type, is_signed)  (    \
+    (sizeof(type) < sizeof(Py_ssize_t))  ||             \
+    (sizeof(type) > sizeof(Py_ssize_t) &&               \
+          likely(v < (type)PY_SSIZE_T_MAX ||            \
+                 v == (type)PY_SSIZE_T_MAX)  &&         \
+          (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||       \
+                                v == (type)PY_SSIZE_T_MIN)))  ||  \
+    (sizeof(type) == sizeof(Py_ssize_t) &&              \
+          (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||        \
+                               v == (type)PY_SSIZE_T_MAX)))  )
+static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject*);
+static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length);
+#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s))
+#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l)
+#define __Pyx_PyBytes_FromString        PyBytes_FromString
+#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(char*);
+#if PY_MAJOR_VERSION < 3
+    #define __Pyx_PyStr_FromString        __Pyx_PyBytes_FromString
+    #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
+#else
+    #define __Pyx_PyStr_FromString        __Pyx_PyUnicode_FromString
+    #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize
+#endif
+#define __Pyx_PyObject_AsSString(s)    ((signed char*) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_AsUString(s)    ((unsigned char*) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_FromUString(s)  __Pyx_PyObject_FromString((char*)s)
+#define __Pyx_PyBytes_FromUString(s)   __Pyx_PyBytes_FromString((char*)s)
+#define __Pyx_PyByteArray_FromUString(s)   __Pyx_PyByteArray_FromString((char*)s)
+#define __Pyx_PyStr_FromUString(s)     __Pyx_PyStr_FromString((char*)s)
+#define __Pyx_PyUnicode_FromUString(s) __Pyx_PyUnicode_FromString((char*)s)
+#if PY_MAJOR_VERSION < 3
+static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
+{
+    const Py_UNICODE *u_end = u;
+    while (*u_end++) ;
+    return u_end - u - 1;
+}
+#else
+#define __Pyx_Py_UNICODE_strlen Py_UNICODE_strlen
+#endif
+#define __Pyx_PyUnicode_FromUnicode(u)       PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u))
+#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode
+#define __Pyx_PyUnicode_AsUnicode            PyUnicode_AsUnicode
+#define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None)
+#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
+static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
+static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
+static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
+static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
+#else
+#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x)
+#endif
+#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
+#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+static int __Pyx_sys_getdefaultencoding_not_ascii;
+static int __Pyx_init_sys_getdefaultencoding_params(void) {
+    PyObject* sys = NULL;
+    PyObject* default_encoding = NULL;
+    PyObject* ascii_chars_u = NULL;
+    PyObject* ascii_chars_b = NULL;
+    sys = PyImport_ImportModule("sys");
+    if (sys == NULL) goto bad;
+    default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL);
+    if (default_encoding == NULL) goto bad;
+    if (strcmp(PyBytes_AsString(default_encoding), "ascii") == 0) {
+        __Pyx_sys_getdefaultencoding_not_ascii = 0;
+    } else {
+        const char* default_encoding_c = PyBytes_AS_STRING(default_encoding);
+        char ascii_chars[128];
+        int c;
+        for (c = 0; c < 128; c++) {
+            ascii_chars[c] = c;
+        }
+        __Pyx_sys_getdefaultencoding_not_ascii = 1;
+        ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL);
+        if (ascii_chars_u == NULL) goto bad;
+        ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL);
+        if (ascii_chars_b == NULL || strncmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) {
+            PyErr_Format(
+                PyExc_ValueError,
+                "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.",
+                default_encoding_c);
+            goto bad;
+        }
+    }
+    Py_XDECREF(sys);
+    Py_XDECREF(default_encoding);
+    Py_XDECREF(ascii_chars_u);
+    Py_XDECREF(ascii_chars_b);
+    return 0;
+bad:
+    Py_XDECREF(sys);
+    Py_XDECREF(default_encoding);
+    Py_XDECREF(ascii_chars_u);
+    Py_XDECREF(ascii_chars_b);
+    return -1;
+}
+#endif
+#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3
+#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL)
+#else
+#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL)
+#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
+static char* __PYX_DEFAULT_STRING_ENCODING;
+static int __Pyx_init_sys_getdefaultencoding_params(void) {
+    PyObject* sys = NULL;
+    PyObject* default_encoding = NULL;
+    char* default_encoding_c;
+    sys = PyImport_ImportModule("sys");
+    if (sys == NULL) goto bad;
+    default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL);
+    if (default_encoding == NULL) goto bad;
+    default_encoding_c = PyBytes_AS_STRING(default_encoding);
+    __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c));
+    strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c);
+    Py_DECREF(sys);
+    Py_DECREF(default_encoding);
+    return 0;
+bad:
+    Py_XDECREF(sys);
+    Py_XDECREF(default_encoding);
+    return -1;
+}
+#endif
+#endif
+
+
+#ifdef __GNUC__
+  /* Test for GCC > 2.95 */
+  #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))
+    #define likely(x)   __builtin_expect(!!(x), 1)
+    #define unlikely(x) __builtin_expect(!!(x), 0)
+  #else /* __GNUC__ > 2 ... */
+    #define likely(x)   (x)
+    #define unlikely(x) (x)
+  #endif /* __GNUC__ > 2 ... */
+#else /* __GNUC__ */
+  #define likely(x)   (x)
+  #define unlikely(x) (x)
+#endif /* __GNUC__ */
+
+static PyObject *__pyx_m;
+static PyObject *__pyx_d;
+static PyObject *__pyx_b;
+static PyObject *__pyx_empty_tuple;
+static PyObject *__pyx_empty_bytes;
+static int __pyx_lineno;
+static int __pyx_clineno = 0;
+static const char * __pyx_cfilenm= __FILE__;
+static const char *__pyx_filename;
+
+
+static const char *__pyx_f[] = {
+  "pybuffer.pyx",
+  "MPI.pxd",
+};
+
+/*--- Type declarations ---*/
+struct PyMPIErrhandlerObject;
+struct PyMPIGroupObject;
+struct PyMPICommObject;
+struct PyMPIIntercommObject;
+struct PyMPIIntracommObject;
+struct PyMPIDistgraphcommObject;
+struct __pyx_obj_8pybuffer_Buffer;
+struct PyMPIRequestObject;
+struct PyMPIGrequestObject;
+struct PyMPIWinObject;
+struct PyMPIDatatypeObject;
+struct PyMPIFileObject;
+struct PyMPIGraphcommObject;
+struct PyMPIPrequestObject;
+struct PyMPIInfoObject;
+struct PyMPICartcommObject;
+struct PyMPIStatusObject;
+struct PyMPIOpObject;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":106
+ *     cdef int      flags
+ * 
+ * ctypedef public api class Errhandler [             # <<<<<<<<<<<<<<
+ *     type   PyMPIErrhandler_Type,
+ *     object PyMPIErrhandlerObject,
+ */
+struct PyMPIErrhandlerObject {
+  PyObject_HEAD
+  MPI_Errhandler ob_mpi;
+  int flags;
+};
+typedef struct PyMPIErrhandlerObject PyMPIErrhandlerObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIErrhandler_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":92
+ *     cdef int    ob_usrid
+ * 
+ * ctypedef public api class Group [             # <<<<<<<<<<<<<<
+ *     type   PyMPIGroup_Type,
+ *     object PyMPIGroupObject,
+ */
+struct PyMPIGroupObject {
+  PyObject_HEAD
+  MPI_Group ob_mpi;
+  int flags;
+};
+typedef struct PyMPIGroupObject PyMPIGroupObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIGroup_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":113
+ *     cdef int            flags
+ * 
+ * ctypedef public api class Comm [             # <<<<<<<<<<<<<<
+ *     type   PyMPIComm_Type,
+ *     object PyMPICommObject,
+ */
+struct PyMPICommObject {
+  PyObject_HEAD
+  MPI_Comm ob_mpi;
+  int flags;
+};
+typedef struct PyMPICommObject PyMPICommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIComm_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":144
+ *     pass
+ * 
+ * ctypedef public api class Intercomm(Comm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIIntercomm_Type,
+ *     object PyMPIIntercommObject,
+ */
+struct PyMPIIntercommObject {
+  struct PyMPICommObject __pyx_base;
+};
+typedef struct PyMPIIntercommObject PyMPIIntercommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIIntercomm_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":120
+ *     cdef int      flags
+ * 
+ * ctypedef public api class Intracomm(Comm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIIntracomm_Type,
+ *     object PyMPIIntracommObject,
+ */
+struct PyMPIIntracommObject {
+  struct PyMPICommObject __pyx_base;
+};
+typedef struct PyMPIIntracommObject PyMPIIntracommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIIntracomm_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":138
+ *     pass
+ * 
+ * ctypedef public api class Distgraphcomm(Intracomm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIDistgraphcomm_Type,
+ *     object PyMPIDistgraphcommObject,
+ */
+struct PyMPIDistgraphcommObject {
+  struct PyMPIIntracommObject __pyx_base;
+};
+typedef struct PyMPIDistgraphcommObject PyMPIDistgraphcommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIDistgraphcomm_Type;
+
+/* "pybuffer.pxd":40
+ *     int  PyBuffer_FillInfo(Py_buffer*, object, void*, Py_ssize_t, bint, int) except -1
+ * 
+ * cdef class Buffer(object):             # <<<<<<<<<<<<<<
+ *     cdef Py_buffer pybuf
+ *     cdef MPI.Datatype dtype
+ */
+struct __pyx_obj_8pybuffer_Buffer {
+  PyObject_HEAD
+  Py_buffer pybuf;
+  struct PyMPIDatatypeObject *dtype;
+  Py_ssize_t items;
+};
+
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":63
+ *     cdef int          flags
+ * 
+ * ctypedef public api class Request [             # <<<<<<<<<<<<<<
+ *     type   PyMPIRequest_Type,
+ *     object PyMPIRequestObject,
+ */
+struct PyMPIRequestObject {
+  PyObject_HEAD
+  MPI_Request ob_mpi;
+  int flags;
+  PyObject *ob_buf;
+};
+typedef struct PyMPIRequestObject PyMPIRequestObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIRequest_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":77
+ *     pass
+ * 
+ * ctypedef public api class Grequest(Request) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIGrequest_Type,
+ *     object PyMPIGrequestObject,
+ */
+struct PyMPIGrequestObject {
+  struct PyMPIRequestObject __pyx_base;
+  MPI_Request ob_grequest;
+};
+typedef struct PyMPIGrequestObject PyMPIGrequestObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIGrequest_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":150
+ *     pass
+ * 
+ * ctypedef public api class Win [             # <<<<<<<<<<<<<<
+ *     type   PyMPIWin_Type,
+ *     object PyMPIWinObject,
+ */
+struct PyMPIWinObject {
+  PyObject_HEAD
+  MPI_Win ob_mpi;
+  int flags;
+};
+typedef struct PyMPIWinObject PyMPIWinObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIWin_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":56
+ *     cdef int        flags
+ * 
+ * ctypedef public api class Datatype [             # <<<<<<<<<<<<<<
+ *     type   PyMPIDatatype_Type,
+ *     object PyMPIDatatypeObject,
+ */
+struct PyMPIDatatypeObject {
+  PyObject_HEAD
+  MPI_Datatype ob_mpi;
+  int flags;
+};
+typedef struct PyMPIDatatypeObject PyMPIDatatypeObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIDatatype_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":157
+ *     cdef int     flags
+ * 
+ * ctypedef public api class File [             # <<<<<<<<<<<<<<
+ *     type   PyMPIFile_Type,
+ *     object PyMPIFileObject,
+ */
+struct PyMPIFileObject {
+  PyObject_HEAD
+  MPI_File ob_mpi;
+  int flags;
+};
+typedef struct PyMPIFileObject PyMPIFileObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIFile_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":132
+ *     pass
+ * 
+ * ctypedef public api class Graphcomm(Intracomm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIGraphcomm_Type,
+ *     object PyMPIGraphcommObject,
+ */
+struct PyMPIGraphcommObject {
+  struct PyMPIIntracommObject __pyx_base;
+};
+typedef struct PyMPIGraphcommObject PyMPIGraphcommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIGraphcomm_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":71
+ *     cdef object      ob_buf
+ * 
+ * ctypedef public api class Prequest(Request) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIPrequest_Type,
+ *     object PyMPIPrequestObject,
+ */
+struct PyMPIPrequestObject {
+  struct PyMPIRequestObject __pyx_base;
+};
+typedef struct PyMPIPrequestObject PyMPIPrequestObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIPrequest_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":99
+ *     cdef int       flags
+ * 
+ * ctypedef public api class Info [             # <<<<<<<<<<<<<<
+ *     type   PyMPIInfo_Type,
+ *     object PyMPIInfoObject,
+ */
+struct PyMPIInfoObject {
+  PyObject_HEAD
+  MPI_Info ob_mpi;
+  int flags;
+};
+typedef struct PyMPIInfoObject PyMPIInfoObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIInfo_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":126
+ *     pass
+ * 
+ * ctypedef public api class Cartcomm(Intracomm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPICartcomm_Type,
+ *     object PyMPICartcommObject,
+ */
+struct PyMPICartcommObject {
+  struct PyMPIIntracommObject __pyx_base;
+};
+typedef struct PyMPICartcommObject PyMPICartcommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPICartcomm_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":49
+ *     ctypedef MPI_Offset Offset "MPI_Offset"
+ * 
+ * ctypedef public api class Status [             # <<<<<<<<<<<<<<
+ *     type   PyMPIStatus_Type,
+ *     object PyMPIStatusObject,
+ */
+struct PyMPIStatusObject {
+  PyObject_HEAD
+  MPI_Status ob_mpi;
+  int flags;
+};
+typedef struct PyMPIStatusObject PyMPIStatusObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIStatus_Type;
+
+/* "/usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":83
+ *     cdef MPI_Request ob_grequest
+ * 
+ * ctypedef public api class Op [             # <<<<<<<<<<<<<<
+ *     type   PyMPIOp_Type,
+ *     object PyMPIOpObject,
+ */
+struct PyMPIOpObject {
+  PyObject_HEAD
+  MPI_Op ob_mpi;
+  int flags;
+  PyObject *(*ob_func)(PyObject *, PyObject *);
+  int ob_usrid;
+};
+typedef struct PyMPIOpObject PyMPIOpObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIOp_Type;
+#ifndef CYTHON_REFNANNY
+  #define CYTHON_REFNANNY 0
+#endif
+#if CYTHON_REFNANNY
+  typedef struct {
+    void (*INCREF)(void*, PyObject*, int);
+    void (*DECREF)(void*, PyObject*, int);
+    void (*GOTREF)(void*, PyObject*, int);
+    void (*GIVEREF)(void*, PyObject*, int);
+    void* (*SetupContext)(const char*, int, const char*);
+    void (*FinishContext)(void**);
+  } __Pyx_RefNannyAPIStruct;
+  static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
+  static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/
+  #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
+#ifdef WITH_THREAD
+  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
+          if (acquire_gil) { \
+              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
+              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+              PyGILState_Release(__pyx_gilstate_save); \
+          } else { \
+              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+          }
+#else
+  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
+          __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+#endif
+  #define __Pyx_RefNannyFinishContext() \
+          __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
+  #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_XINCREF(r)  do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0)
+  #define __Pyx_XDECREF(r)  do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0)
+  #define __Pyx_XGOTREF(r)  do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0)
+  #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
+#else
+  #define __Pyx_RefNannyDeclarations
+  #define __Pyx_RefNannySetupContext(name, acquire_gil)
+  #define __Pyx_RefNannyFinishContext()
+  #define __Pyx_INCREF(r) Py_INCREF(r)
+  #define __Pyx_DECREF(r) Py_DECREF(r)
+  #define __Pyx_GOTREF(r)
+  #define __Pyx_GIVEREF(r)
+  #define __Pyx_XINCREF(r) Py_XINCREF(r)
+  #define __Pyx_XDECREF(r) Py_XDECREF(r)
+  #define __Pyx_XGOTREF(r)
+  #define __Pyx_XGIVEREF(r)
+#endif /* CYTHON_REFNANNY */
+#define __Pyx_XDECREF_SET(r, v) do {                            \
+        PyObject *tmp = (PyObject *) r;                         \
+        r = v; __Pyx_XDECREF(tmp);                              \
+    } while (0)
+#define __Pyx_DECREF_SET(r, v) do {                             \
+        PyObject *tmp = (PyObject *) r;                         \
+        r = v; __Pyx_DECREF(tmp);                               \
+    } while (0)
+#define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
+#define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) {
+    PyTypeObject* tp = Py_TYPE(obj);
+    if (likely(tp->tp_getattro))
+        return tp->tp_getattro(obj, attr_name);
+#if PY_MAJOR_VERSION < 3
+    if (likely(tp->tp_getattr))
+        return tp->tp_getattr(obj, PyString_AS_STRING(attr_name));
+#endif
+    return PyObject_GetAttr(obj, attr_name);
+}
+#else
+#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n)
+#endif
+
+static PyObject *__Pyx_GetBuiltinName(PyObject *name); /*proto*/
+
+static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
+static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
+
+static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); /*proto*/
+
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
+    PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
+    const char* function_name); /*proto*/
+
+static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
+    Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
+
+static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
+static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
+
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /*proto*/
+
+#if PY_MAJOR_VERSION >= 3
+static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
+    PyObject *value;
+    value = PyDict_GetItemWithError(d, key);
+    if (unlikely(!value)) {
+        if (!PyErr_Occurred()) {
+            PyObject* args = PyTuple_Pack(1, key);
+            if (likely(args))
+                PyErr_SetObject(PyExc_KeyError, args);
+            Py_XDECREF(args);
+        }
+        return NULL;
+    }
+    Py_INCREF(value);
+    return value;
+}
+#else
+    #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key)
+#endif
+
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
+
+static CYTHON_INLINE Py_ssize_t __Pyx_div_Py_ssize_t(Py_ssize_t, Py_ssize_t); /* proto */
+
+#ifndef __PYX_FORCE_INIT_THREADS
+  #define __PYX_FORCE_INIT_THREADS 0
+#endif
+
+#define UNARY_NEG_WOULD_OVERFLOW(x)            (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
+
+static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name); /*proto*/
+
+static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name); /*proto*/
+
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); /*proto*/
+
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value);
+
+static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *);
+
+static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *);
+
+static int __Pyx_check_binary_version(void);
+
+#if !defined(__Pyx_PyIdentifier_FromString)
+#if PY_MAJOR_VERSION < 3
+  #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s)
+#else
+  #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s)
+#endif
+#endif
+
+static PyObject *__Pyx_ImportModule(const char *name); /*proto*/
+
+static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict);  /*proto*/
+
+typedef struct {
+    int code_line;
+    PyCodeObject* code_object;
+} __Pyx_CodeObjectCacheEntry;
+struct __Pyx_CodeObjectCache {
+    int count;
+    int max_count;
+    __Pyx_CodeObjectCacheEntry* entries;
+};
+static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
+static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
+static PyCodeObject *__pyx_find_code_object(int code_line);
+static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
+
+static void __Pyx_AddTraceback(const char *funcname, int c_line,
+                               int py_line, const char *filename); /*proto*/
+
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
+
+
+/* Module declarations from 'mpi4py.MPI' */
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Status = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Datatype = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Request = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Prequest = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Grequest = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Op = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Group = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Info = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Errhandler = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Comm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Intracomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Cartcomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Graphcomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Distgraphcomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Intercomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Win = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_File = 0;
+
+/* Module declarations from 'mpi4py.mpi_c' */
+
+/* Module declarations from 'cpython.ref' */
+
+/* Module declarations from 'libc.string' */
+
+/* Module declarations from 'libc.stdlib' */
+
+/* Module declarations from 'pybuffer' */
+static PyTypeObject *__pyx_ptype_8pybuffer_Buffer = 0;
+static PyObject *__pyx_v_8pybuffer_TypeDict = 0;
+static int __pyx_v_8pybuffer_bufflags;
+static PyObject *__pyx_f_8pybuffer_getformat(Py_buffer *); /*proto*/
+#define __Pyx_MODULE_NAME "pybuffer"
+int __pyx_module_is_main_pybuffer = 0;
+
+/* Implementation of 'pybuffer' */
+static PyObject *__pyx_builtin_AttributeError;
+static PyObject *__pyx_builtin_TypeError;
+static int __pyx_pf_8pybuffer_6Buffer___cinit__(struct __pyx_obj_8pybuffer_Buffer *__pyx_v_self, PyObject *__pyx_v_data); /* proto */
+static void __pyx_pf_8pybuffer_6Buffer_2__dealloc__(struct __pyx_obj_8pybuffer_Buffer *__pyx_v_self); /* proto */
+static PyObject *__pyx_tp_new_8pybuffer_Buffer(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static char __pyx_k_B[] = "B";
+static char __pyx_k_D[] = "D";
+static char __pyx_k_F[] = "F";
+static char __pyx_k_G[] = "G";
+static char __pyx_k_H[] = "H";
+static char __pyx_k_I[] = "I";
+static char __pyx_k_L[] = "L";
+static char __pyx_k_Q[] = "Q";
+static char __pyx_k_b[] = "b";
+static char __pyx_k_c[] = "c";
+static char __pyx_k_d[] = "d";
+static char __pyx_k_f[] = "f";
+static char __pyx_k_g[] = "g";
+static char __pyx_k_h[] = "h";
+static char __pyx_k_i[] = "i";
+static char __pyx_k_l[] = "l";
+static char __pyx_k_p[] = "p";
+static char __pyx_k_q[] = "q";
+static char __pyx_k_Zd[] = "Zd";
+static char __pyx_k_Zf[] = "Zf";
+static char __pyx_k_Zg[] = "Zg";
+static char __pyx_k__2[] = "?";
+static char __pyx_k_INT[] = "INT";
+static char __pyx_k_MPI[] = "MPI";
+static char __pyx_k_AINT[] = "AINT";
+static char __pyx_k_CHAR[] = "CHAR";
+static char __pyx_k_LONG[] = "LONG";
+static char __pyx_k_char[] = "char";
+static char __pyx_k_data[] = "data";
+static char __pyx_k_main[] = "__main__";
+static char __pyx_k_test[] = "__test__";
+static char __pyx_k_FLOAT[] = "FLOAT";
+static char __pyx_k_SHORT[] = "SHORT";
+static char __pyx_k_dtype[] = "dtype";
+static char __pyx_k_C_BOOL[] = "C_BOOL";
+static char __pyx_k_DOUBLE[] = "DOUBLE";
+static char __pyx_k_import[] = "__import__";
+static char __pyx_k_mpi4py[] = "mpi4py";
+static char __pyx_k_UNSIGNED[] = "UNSIGNED";
+static char __pyx_k_typecode[] = "typecode";
+static char __pyx_k_LONG_LONG[] = "LONG_LONG";
+static char __pyx_k_TypeError[] = "TypeError";
+static char __pyx_k_LONG_DOUBLE[] = "LONG_DOUBLE";
+static char __pyx_k_SIGNED_CHAR[] = "SIGNED_CHAR";
+static char __pyx_k_UNSIGNED_CHAR[] = "UNSIGNED_CHAR";
+static char __pyx_k_UNSIGNED_LONG[] = "UNSIGNED_LONG";
+static char __pyx_k_AttributeError[] = "AttributeError";
+static char __pyx_k_UNSIGNED_SHORT[] = "UNSIGNED_SHORT";
+static char __pyx_k_C_FLOAT_COMPLEX[] = "C_FLOAT_COMPLEX";
+static char __pyx_k_C_DOUBLE_COMPLEX[] = "C_DOUBLE_COMPLEX";
+static char __pyx_k_UNSIGNED_LONG_LONG[] = "UNSIGNED_LONG_LONG";
+static char __pyx_k_C_LONG_DOUBLE_COMPLEX[] = "C_LONG_DOUBLE_COMPLEX";
+static char __pyx_k_object_does_not_present_buffer_i[] = "object does not present buffer interface";
+static PyObject *__pyx_n_s_AINT;
+static PyObject *__pyx_n_s_AttributeError;
+static PyObject *__pyx_n_s_B;
+static PyObject *__pyx_n_s_CHAR;
+static PyObject *__pyx_n_s_C_BOOL;
+static PyObject *__pyx_n_s_C_DOUBLE_COMPLEX;
+static PyObject *__pyx_n_s_C_FLOAT_COMPLEX;
+static PyObject *__pyx_n_s_C_LONG_DOUBLE_COMPLEX;
+static PyObject *__pyx_n_s_D;
+static PyObject *__pyx_n_s_DOUBLE;
+static PyObject *__pyx_n_s_F;
+static PyObject *__pyx_n_s_FLOAT;
+static PyObject *__pyx_n_s_G;
+static PyObject *__pyx_n_s_H;
+static PyObject *__pyx_n_s_I;
+static PyObject *__pyx_n_s_INT;
+static PyObject *__pyx_n_s_L;
+static PyObject *__pyx_n_s_LONG;
+static PyObject *__pyx_n_s_LONG_DOUBLE;
+static PyObject *__pyx_n_s_LONG_LONG;
+static PyObject *__pyx_n_s_MPI;
+static PyObject *__pyx_n_s_Q;
+static PyObject *__pyx_n_s_SHORT;
+static PyObject *__pyx_n_s_SIGNED_CHAR;
+static PyObject *__pyx_n_s_TypeError;
+static PyObject *__pyx_n_s_UNSIGNED;
+static PyObject *__pyx_n_s_UNSIGNED_CHAR;
+static PyObject *__pyx_n_s_UNSIGNED_LONG;
+static PyObject *__pyx_n_s_UNSIGNED_LONG_LONG;
+static PyObject *__pyx_n_s_UNSIGNED_SHORT;
+static PyObject *__pyx_n_s_Zd;
+static PyObject *__pyx_n_s_Zf;
+static PyObject *__pyx_n_s_Zg;
+static PyObject *__pyx_kp_s__2;
+static PyObject *__pyx_n_s_b;
+static PyObject *__pyx_n_s_c;
+static PyObject *__pyx_n_s_char;
+static PyObject *__pyx_n_s_d;
+static PyObject *__pyx_n_s_data;
+static PyObject *__pyx_n_s_dtype;
+static PyObject *__pyx_n_s_f;
+static PyObject *__pyx_n_s_g;
+static PyObject *__pyx_n_s_h;
+static PyObject *__pyx_n_s_i;
+static PyObject *__pyx_n_s_import;
+static PyObject *__pyx_n_s_l;
+static PyObject *__pyx_n_s_main;
+static PyObject *__pyx_n_s_mpi4py;
+static PyObject *__pyx_kp_s_object_does_not_present_buffer_i;
+static PyObject *__pyx_n_s_p;
+static PyObject *__pyx_n_s_q;
+static PyObject *__pyx_n_s_test;
+static PyObject *__pyx_n_s_typecode;
+static PyObject *__pyx_tuple_;
+
+/* "pybuffer.pyx":39
+ * }
+ * 
+ * cdef object getformat(Py_buffer* pybuf):             # <<<<<<<<<<<<<<
+ *     cdef object obj = <object> pybuf.obj
+ * 
+ */
+
+static PyObject *__pyx_f_8pybuffer_getformat(Py_buffer *__pyx_v_pybuf) {
+  PyObject *__pyx_v_obj = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
+  int __pyx_t_7;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("getformat", 0);
+
+  /* "pybuffer.pyx":40
+ * 
+ * cdef object getformat(Py_buffer* pybuf):
+ *     cdef object obj = <object> pybuf.obj             # <<<<<<<<<<<<<<
+ * 
+ *     # numpy.ndarray
+ */
+  __pyx_t_1 = ((PyObject *)__pyx_v_pybuf->obj);
+  __Pyx_INCREF(__pyx_t_1);
+  __pyx_v_obj = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":43
+ * 
+ *     # numpy.ndarray
+ *     try: return obj.dtype.char             # <<<<<<<<<<<<<<
+ *     except (AttributeError, TypeError): pass
+ * 
+ */
+  {
+    __Pyx_ExceptionSave(&__pyx_t_2, &__pyx_t_3, &__pyx_t_4);
+    __Pyx_XGOTREF(__pyx_t_2);
+    __Pyx_XGOTREF(__pyx_t_3);
+    __Pyx_XGOTREF(__pyx_t_4);
+    /*try:*/ {
+      __Pyx_XDECREF(__pyx_r);
+      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj, __pyx_n_s_dtype); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_char); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __pyx_r = __pyx_t_5;
+      __pyx_t_5 = 0;
+      goto __pyx_L7_try_return;
+    }
+    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    goto __pyx_L10_try_end;
+    __pyx_L3_error:;
+    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+
+    /* "pybuffer.pyx":44
+ *     # numpy.ndarray
+ *     try: return obj.dtype.char
+ *     except (AttributeError, TypeError): pass             # <<<<<<<<<<<<<<
+ * 
+ *     # array.array
+ */
+    __pyx_t_6 = PyErr_ExceptionMatches(__pyx_builtin_AttributeError) || PyErr_ExceptionMatches(__pyx_builtin_TypeError);
+    if (__pyx_t_6) {
+      PyErr_Restore(0,0,0);
+      goto __pyx_L4_exception_handled;
+    }
+    goto __pyx_L5_except_error;
+    __pyx_L5_except_error:;
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_XGIVEREF(__pyx_t_4);
+    __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4);
+    goto __pyx_L1_error;
+    __pyx_L7_try_return:;
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_XGIVEREF(__pyx_t_4);
+    __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4);
+    goto __pyx_L0;
+    __pyx_L4_exception_handled:;
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_XGIVEREF(__pyx_t_4);
+    __Pyx_ExceptionReset(__pyx_t_2, __pyx_t_3, __pyx_t_4);
+    __pyx_L10_try_end:;
+  }
+
+  /* "pybuffer.pyx":47
+ * 
+ *     # array.array
+ *     try: return obj.typecode             # <<<<<<<<<<<<<<
+ *     except (AttributeError, TypeError): pass
+ * 
+ */
+  {
+    __Pyx_ExceptionSave(&__pyx_t_4, &__pyx_t_3, &__pyx_t_2);
+    __Pyx_XGOTREF(__pyx_t_4);
+    __Pyx_XGOTREF(__pyx_t_3);
+    __Pyx_XGOTREF(__pyx_t_2);
+    /*try:*/ {
+      __Pyx_XDECREF(__pyx_r);
+      __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_obj, __pyx_n_s_typecode); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L11_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_r = __pyx_t_5;
+      __pyx_t_5 = 0;
+      goto __pyx_L15_try_return;
+    }
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+    goto __pyx_L18_try_end;
+    __pyx_L11_error:;
+    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+
+    /* "pybuffer.pyx":48
+ *     # array.array
+ *     try: return obj.typecode
+ *     except (AttributeError, TypeError): pass             # <<<<<<<<<<<<<<
+ * 
+ *     if pybuf.format is NULL: return "B"
+ */
+    __pyx_t_6 = PyErr_ExceptionMatches(__pyx_builtin_AttributeError) || PyErr_ExceptionMatches(__pyx_builtin_TypeError);
+    if (__pyx_t_6) {
+      PyErr_Restore(0,0,0);
+      goto __pyx_L12_exception_handled;
+    }
+    goto __pyx_L13_except_error;
+    __pyx_L13_except_error:;
+    __Pyx_XGIVEREF(__pyx_t_4);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_ExceptionReset(__pyx_t_4, __pyx_t_3, __pyx_t_2);
+    goto __pyx_L1_error;
+    __pyx_L15_try_return:;
+    __Pyx_XGIVEREF(__pyx_t_4);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_ExceptionReset(__pyx_t_4, __pyx_t_3, __pyx_t_2);
+    goto __pyx_L0;
+    __pyx_L12_exception_handled:;
+    __Pyx_XGIVEREF(__pyx_t_4);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_ExceptionReset(__pyx_t_4, __pyx_t_3, __pyx_t_2);
+    __pyx_L18_try_end:;
+  }
+
+  /* "pybuffer.pyx":50
+ *     except (AttributeError, TypeError): pass
+ * 
+ *     if pybuf.format is NULL: return "B"             # <<<<<<<<<<<<<<
+ *     return PyUnicodeString_FromString(pybuf.format)
+ * 
+ */
+  __pyx_t_7 = ((__pyx_v_pybuf->format == NULL) != 0);
+  if (__pyx_t_7) {
+    __Pyx_XDECREF(__pyx_r);
+    __Pyx_INCREF(__pyx_n_s_B);
+    __pyx_r = __pyx_n_s_B;
+    goto __pyx_L0;
+  }
+
+  /* "pybuffer.pyx":51
+ * 
+ *     if pybuf.format is NULL: return "B"
+ *     return PyUnicodeString_FromString(pybuf.format)             # <<<<<<<<<<<<<<
+ * 
+ * cdef int bufflags = PyBUF_ANY_CONTIGUOUS | PyBUF_WRITABLE | PyBUF_FORMAT
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_5 = PyUnicodeString_FromString(__pyx_v_pybuf->format); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_r = __pyx_t_5;
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
+
+  /* "pybuffer.pyx":39
+ * }
+ * 
+ * cdef object getformat(Py_buffer* pybuf):             # <<<<<<<<<<<<<<
+ *     cdef object obj = <object> pybuf.obj
+ * 
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("pybuffer.getformat", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_obj);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pybuffer.pyx":56
+ * 
+ * cdef class Buffer(object):
+ *     def __cinit__(self, object data):             # <<<<<<<<<<<<<<
+ *         if not PyObject_CheckBuffer(data):
+ *             raise TypeError("object does not present buffer interface")
+ */
+
+/* Python wrapper */
+static int __pyx_pw_8pybuffer_6Buffer_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_8pybuffer_6Buffer_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_data = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_data,0};
+    PyObject* values[1] = {0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_data)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+    }
+    __pyx_v_data = values[0];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pybuffer.Buffer.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_8pybuffer_6Buffer___cinit__(((struct __pyx_obj_8pybuffer_Buffer *)__pyx_v_self), __pyx_v_data);
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_8pybuffer_6Buffer___cinit__(struct __pyx_obj_8pybuffer_Buffer *__pyx_v_self, PyObject *__pyx_v_data) {
+  Py_buffer *__pyx_v_pybuf;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pybuffer.pyx":57
+ * cdef class Buffer(object):
+ *     def __cinit__(self, object data):
+ *         if not PyObject_CheckBuffer(data):             # <<<<<<<<<<<<<<
+ *             raise TypeError("object does not present buffer interface")
+ * 
+ */
+  __pyx_t_1 = ((!(PyObject_CheckBuffer(__pyx_v_data) != 0)) != 0);
+  if (__pyx_t_1) {
+
+    /* "pybuffer.pyx":58
+ *     def __cinit__(self, object data):
+ *         if not PyObject_CheckBuffer(data):
+ *             raise TypeError("object does not present buffer interface")             # <<<<<<<<<<<<<<
+ * 
+ *         cdef Py_buffer* pybuf = &self.pybuf
+ */
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+
+  /* "pybuffer.pyx":60
+ *             raise TypeError("object does not present buffer interface")
+ * 
+ *         cdef Py_buffer* pybuf = &self.pybuf             # <<<<<<<<<<<<<<
+ *         PyObject_GetBuffer(data, pybuf, bufflags)
+ *         self.dtype = TypeDict[getformat(pybuf)]
+ */
+  __pyx_v_pybuf = (&__pyx_v_self->pybuf);
+
+  /* "pybuffer.pyx":61
+ * 
+ *         cdef Py_buffer* pybuf = &self.pybuf
+ *         PyObject_GetBuffer(data, pybuf, bufflags)             # <<<<<<<<<<<<<<
+ *         self.dtype = TypeDict[getformat(pybuf)]
+ *         self.items = pybuf.len / pybuf.itemsize
+ */
+  __pyx_t_3 = PyObject_GetBuffer(__pyx_v_data, __pyx_v_pybuf, __pyx_v_8pybuffer_bufflags); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pybuffer.pyx":62
+ *         cdef Py_buffer* pybuf = &self.pybuf
+ *         PyObject_GetBuffer(data, pybuf, bufflags)
+ *         self.dtype = TypeDict[getformat(pybuf)]             # <<<<<<<<<<<<<<
+ *         self.items = pybuf.len / pybuf.itemsize
+ * 
+ */
+  if (unlikely(__pyx_v_8pybuffer_TypeDict == Py_None)) {
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_2 = __pyx_f_8pybuffer_getformat(__pyx_v_pybuf); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v_8pybuffer_TypeDict, __pyx_t_2); if (unlikely(__pyx_t_4 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_6mpi4py_3MPI_Datatype))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GIVEREF(__pyx_t_4);
+  __Pyx_GOTREF(__pyx_v_self->dtype);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->dtype));
+  __pyx_v_self->dtype = ((struct PyMPIDatatypeObject *)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+  /* "pybuffer.pyx":63
+ *         PyObject_GetBuffer(data, pybuf, bufflags)
+ *         self.dtype = TypeDict[getformat(pybuf)]
+ *         self.items = pybuf.len / pybuf.itemsize             # <<<<<<<<<<<<<<
+ * 
+ *     def __dealloc__(self):
+ */
+  if (unlikely(__pyx_v_pybuf->itemsize == 0)) {
+    #ifdef WITH_THREAD
+    PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();
+    #endif
+    PyErr_SetString(PyExc_ZeroDivisionError, "integer division or modulo by zero");
+    #ifdef WITH_THREAD
+    PyGILState_Release(__pyx_gilstate_save);
+    #endif
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  else if (sizeof(Py_ssize_t) == sizeof(long) && unlikely(__pyx_v_pybuf->itemsize == -1)  && unlikely(UNARY_NEG_WOULD_OVERFLOW(__pyx_v_pybuf->len))) {
+    #ifdef WITH_THREAD
+    PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();
+    #endif
+    PyErr_SetString(PyExc_OverflowError, "value too large to perform division");
+    #ifdef WITH_THREAD
+    PyGILState_Release(__pyx_gilstate_save);
+    #endif
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_v_self->items = __Pyx_div_Py_ssize_t(__pyx_v_pybuf->len, __pyx_v_pybuf->itemsize);
+
+  /* "pybuffer.pyx":56
+ * 
+ * cdef class Buffer(object):
+ *     def __cinit__(self, object data):             # <<<<<<<<<<<<<<
+ *         if not PyObject_CheckBuffer(data):
+ *             raise TypeError("object does not present buffer interface")
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("pybuffer.Buffer.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pybuffer.pyx":65
+ *         self.items = pybuf.len / pybuf.itemsize
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         PyBuffer_Release(&self.pybuf)
+ */
+
+/* Python wrapper */
+static void __pyx_pw_8pybuffer_6Buffer_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_8pybuffer_6Buffer_3__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_8pybuffer_6Buffer_2__dealloc__(((struct __pyx_obj_8pybuffer_Buffer *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+static void __pyx_pf_8pybuffer_6Buffer_2__dealloc__(struct __pyx_obj_8pybuffer_Buffer *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
+
+  /* "pybuffer.pyx":66
+ * 
+ *     def __dealloc__(self):
+ *         PyBuffer_Release(&self.pybuf)             # <<<<<<<<<<<<<<
+ */
+  PyBuffer_Release((&__pyx_v_self->pybuf));
+
+  /* "pybuffer.pyx":65
+ *         self.items = pybuf.len / pybuf.itemsize
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         PyBuffer_Release(&self.pybuf)
+ */
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+static PyObject *__pyx_tp_new_8pybuffer_Buffer(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_8pybuffer_Buffer *p;
+  PyObject *o;
+  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
+    o = (*t->tp_alloc)(t, 0);
+  } else {
+    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
+  }
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_8pybuffer_Buffer *)o);
+  p->dtype = ((struct PyMPIDatatypeObject *)Py_None); Py_INCREF(Py_None);
+  p->pybuf.obj = NULL;
+  if (unlikely(__pyx_pw_8pybuffer_6Buffer_1__cinit__(o, a, k) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_8pybuffer_Buffer(PyObject *o) {
+  struct __pyx_obj_8pybuffer_Buffer *p = (struct __pyx_obj_8pybuffer_Buffer *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  {
+    PyObject *etype, *eval, *etb;
+    PyErr_Fetch(&etype, &eval, &etb);
+    ++Py_REFCNT(o);
+    __pyx_pw_8pybuffer_6Buffer_3__dealloc__(o);
+    --Py_REFCNT(o);
+    PyErr_Restore(etype, eval, etb);
+  }
+  Py_CLEAR(p->dtype);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_8pybuffer_Buffer(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_8pybuffer_Buffer *p = (struct __pyx_obj_8pybuffer_Buffer *)o;
+  if (p->dtype) {
+    e = (*v)(((PyObject*)p->dtype), a); if (e) return e;
+  }
+  if (p->pybuf.obj) {
+    e = (*v)(p->pybuf.obj, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_8pybuffer_Buffer(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_8pybuffer_Buffer *p = (struct __pyx_obj_8pybuffer_Buffer *)o;
+  tmp = ((PyObject*)p->dtype);
+  p->dtype = ((struct PyMPIDatatypeObject *)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  Py_CLEAR(p->pybuf.obj);
+  return 0;
+}
+
+static PyMethodDef __pyx_methods_8pybuffer_Buffer[] = {
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_8pybuffer_Buffer = {
+  PyVarObject_HEAD_INIT(0, 0)
+  __Pyx_NAMESTR("pybuffer.Buffer"), /*tp_name*/
+  sizeof(struct __pyx_obj_8pybuffer_Buffer), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_8pybuffer_Buffer, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  0, /*tp_doc*/
+  __pyx_tp_traverse_8pybuffer_Buffer, /*tp_traverse*/
+  __pyx_tp_clear_8pybuffer_Buffer, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_8pybuffer_Buffer, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_8pybuffer_Buffer, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  #if PY_VERSION_HEX >= 0x02060000
+  0, /*tp_version_tag*/
+  #endif
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+
+static PyMethodDef __pyx_methods[] = {
+  {0, 0, 0, 0}
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef __pyx_moduledef = {
+  #if PY_VERSION_HEX < 0x03020000
+    { PyObject_HEAD_INIT(NULL) NULL, 0, NULL },
+  #else
+    PyModuleDef_HEAD_INIT,
+  #endif
+    __Pyx_NAMESTR("pybuffer"),
+    0, /* m_doc */
+    -1, /* m_size */
+    __pyx_methods /* m_methods */,
+    NULL, /* m_reload */
+    NULL, /* m_traverse */
+    NULL, /* m_clear */
+    NULL /* m_free */
+};
+#endif
+
+static __Pyx_StringTabEntry __pyx_string_tab[] = {
+  {&__pyx_n_s_AINT, __pyx_k_AINT, sizeof(__pyx_k_AINT), 0, 0, 1, 1},
+  {&__pyx_n_s_AttributeError, __pyx_k_AttributeError, sizeof(__pyx_k_AttributeError), 0, 0, 1, 1},
+  {&__pyx_n_s_B, __pyx_k_B, sizeof(__pyx_k_B), 0, 0, 1, 1},
+  {&__pyx_n_s_CHAR, __pyx_k_CHAR, sizeof(__pyx_k_CHAR), 0, 0, 1, 1},
+  {&__pyx_n_s_C_BOOL, __pyx_k_C_BOOL, sizeof(__pyx_k_C_BOOL), 0, 0, 1, 1},
+  {&__pyx_n_s_C_DOUBLE_COMPLEX, __pyx_k_C_DOUBLE_COMPLEX, sizeof(__pyx_k_C_DOUBLE_COMPLEX), 0, 0, 1, 1},
+  {&__pyx_n_s_C_FLOAT_COMPLEX, __pyx_k_C_FLOAT_COMPLEX, sizeof(__pyx_k_C_FLOAT_COMPLEX), 0, 0, 1, 1},
+  {&__pyx_n_s_C_LONG_DOUBLE_COMPLEX, __pyx_k_C_LONG_DOUBLE_COMPLEX, sizeof(__pyx_k_C_LONG_DOUBLE_COMPLEX), 0, 0, 1, 1},
+  {&__pyx_n_s_D, __pyx_k_D, sizeof(__pyx_k_D), 0, 0, 1, 1},
+  {&__pyx_n_s_DOUBLE, __pyx_k_DOUBLE, sizeof(__pyx_k_DOUBLE), 0, 0, 1, 1},
+  {&__pyx_n_s_F, __pyx_k_F, sizeof(__pyx_k_F), 0, 0, 1, 1},
+  {&__pyx_n_s_FLOAT, __pyx_k_FLOAT, sizeof(__pyx_k_FLOAT), 0, 0, 1, 1},
+  {&__pyx_n_s_G, __pyx_k_G, sizeof(__pyx_k_G), 0, 0, 1, 1},
+  {&__pyx_n_s_H, __pyx_k_H, sizeof(__pyx_k_H), 0, 0, 1, 1},
+  {&__pyx_n_s_I, __pyx_k_I, sizeof(__pyx_k_I), 0, 0, 1, 1},
+  {&__pyx_n_s_INT, __pyx_k_INT, sizeof(__pyx_k_INT), 0, 0, 1, 1},
+  {&__pyx_n_s_L, __pyx_k_L, sizeof(__pyx_k_L), 0, 0, 1, 1},
+  {&__pyx_n_s_LONG, __pyx_k_LONG, sizeof(__pyx_k_LONG), 0, 0, 1, 1},
+  {&__pyx_n_s_LONG_DOUBLE, __pyx_k_LONG_DOUBLE, sizeof(__pyx_k_LONG_DOUBLE), 0, 0, 1, 1},
+  {&__pyx_n_s_LONG_LONG, __pyx_k_LONG_LONG, sizeof(__pyx_k_LONG_LONG), 0, 0, 1, 1},
+  {&__pyx_n_s_MPI, __pyx_k_MPI, sizeof(__pyx_k_MPI), 0, 0, 1, 1},
+  {&__pyx_n_s_Q, __pyx_k_Q, sizeof(__pyx_k_Q), 0, 0, 1, 1},
+  {&__pyx_n_s_SHORT, __pyx_k_SHORT, sizeof(__pyx_k_SHORT), 0, 0, 1, 1},
+  {&__pyx_n_s_SIGNED_CHAR, __pyx_k_SIGNED_CHAR, sizeof(__pyx_k_SIGNED_CHAR), 0, 0, 1, 1},
+  {&__pyx_n_s_TypeError, __pyx_k_TypeError, sizeof(__pyx_k_TypeError), 0, 0, 1, 1},
+  {&__pyx_n_s_UNSIGNED, __pyx_k_UNSIGNED, sizeof(__pyx_k_UNSIGNED), 0, 0, 1, 1},
+  {&__pyx_n_s_UNSIGNED_CHAR, __pyx_k_UNSIGNED_CHAR, sizeof(__pyx_k_UNSIGNED_CHAR), 0, 0, 1, 1},
+  {&__pyx_n_s_UNSIGNED_LONG, __pyx_k_UNSIGNED_LONG, sizeof(__pyx_k_UNSIGNED_LONG), 0, 0, 1, 1},
+  {&__pyx_n_s_UNSIGNED_LONG_LONG, __pyx_k_UNSIGNED_LONG_LONG, sizeof(__pyx_k_UNSIGNED_LONG_LONG), 0, 0, 1, 1},
+  {&__pyx_n_s_UNSIGNED_SHORT, __pyx_k_UNSIGNED_SHORT, sizeof(__pyx_k_UNSIGNED_SHORT), 0, 0, 1, 1},
+  {&__pyx_n_s_Zd, __pyx_k_Zd, sizeof(__pyx_k_Zd), 0, 0, 1, 1},
+  {&__pyx_n_s_Zf, __pyx_k_Zf, sizeof(__pyx_k_Zf), 0, 0, 1, 1},
+  {&__pyx_n_s_Zg, __pyx_k_Zg, sizeof(__pyx_k_Zg), 0, 0, 1, 1},
+  {&__pyx_kp_s__2, __pyx_k__2, sizeof(__pyx_k__2), 0, 0, 1, 0},
+  {&__pyx_n_s_b, __pyx_k_b, sizeof(__pyx_k_b), 0, 0, 1, 1},
+  {&__pyx_n_s_c, __pyx_k_c, sizeof(__pyx_k_c), 0, 0, 1, 1},
+  {&__pyx_n_s_char, __pyx_k_char, sizeof(__pyx_k_char), 0, 0, 1, 1},
+  {&__pyx_n_s_d, __pyx_k_d, sizeof(__pyx_k_d), 0, 0, 1, 1},
+  {&__pyx_n_s_data, __pyx_k_data, sizeof(__pyx_k_data), 0, 0, 1, 1},
+  {&__pyx_n_s_dtype, __pyx_k_dtype, sizeof(__pyx_k_dtype), 0, 0, 1, 1},
+  {&__pyx_n_s_f, __pyx_k_f, sizeof(__pyx_k_f), 0, 0, 1, 1},
+  {&__pyx_n_s_g, __pyx_k_g, sizeof(__pyx_k_g), 0, 0, 1, 1},
+  {&__pyx_n_s_h, __pyx_k_h, sizeof(__pyx_k_h), 0, 0, 1, 1},
+  {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1},
+  {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1},
+  {&__pyx_n_s_l, __pyx_k_l, sizeof(__pyx_k_l), 0, 0, 1, 1},
+  {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1},
+  {&__pyx_n_s_mpi4py, __pyx_k_mpi4py, sizeof(__pyx_k_mpi4py), 0, 0, 1, 1},
+  {&__pyx_kp_s_object_does_not_present_buffer_i, __pyx_k_object_does_not_present_buffer_i, sizeof(__pyx_k_object_does_not_present_buffer_i), 0, 0, 1, 0},
+  {&__pyx_n_s_p, __pyx_k_p, sizeof(__pyx_k_p), 0, 0, 1, 1},
+  {&__pyx_n_s_q, __pyx_k_q, sizeof(__pyx_k_q), 0, 0, 1, 1},
+  {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1},
+  {&__pyx_n_s_typecode, __pyx_k_typecode, sizeof(__pyx_k_typecode), 0, 0, 1, 1},
+  {0, 0, 0, 0, 0, 0, 0}
+};
+static int __Pyx_InitCachedBuiltins(void) {
+  __pyx_builtin_AttributeError = __Pyx_GetBuiltinName(__pyx_n_s_AttributeError); if (!__pyx_builtin_AttributeError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_TypeError = __Pyx_GetBuiltinName(__pyx_n_s_TypeError); if (!__pyx_builtin_TypeError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  return 0;
+  __pyx_L1_error:;
+  return -1;
+}
+
+static int __Pyx_InitCachedConstants(void) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
+
+  /* "pybuffer.pyx":58
+ *     def __cinit__(self, object data):
+ *         if not PyObject_CheckBuffer(data):
+ *             raise TypeError("object does not present buffer interface")             # <<<<<<<<<<<<<<
+ * 
+ *         cdef Py_buffer* pybuf = &self.pybuf
+ */
+  __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_object_does_not_present_buffer_i); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple_);
+  __Pyx_GIVEREF(__pyx_tuple_);
+  __Pyx_RefNannyFinishContext();
+  return 0;
+  __pyx_L1_error:;
+  __Pyx_RefNannyFinishContext();
+  return -1;
+}
+
+static int __Pyx_InitGlobals(void) {
+  if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  return 0;
+  __pyx_L1_error:;
+  return -1;
+}
+
+#if PY_MAJOR_VERSION < 3
+PyMODINIT_FUNC initpybuffer(void); /*proto*/
+PyMODINIT_FUNC initpybuffer(void)
+#else
+PyMODINIT_FUNC PyInit_pybuffer(void); /*proto*/
+PyMODINIT_FUNC PyInit_pybuffer(void)
+#endif
+{
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannyDeclarations
+  #if CYTHON_REFNANNY
+  __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny");
+  if (!__Pyx_RefNanny) {
+      PyErr_Clear();
+      __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny");
+      if (!__Pyx_RefNanny)
+          Py_FatalError("failed to import 'refnanny' module");
+  }
+  #endif
+  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_pybuffer(void)", 0);
+  if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #ifdef __Pyx_CyFunction_USED
+  if (__Pyx_CyFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  #ifdef __Pyx_FusedFunction_USED
+  if (__pyx_FusedFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  #ifdef __Pyx_Generator_USED
+  if (__pyx_Generator_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  /*--- Library function declarations ---*/
+  /*--- Threads initialization code ---*/
+  #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS
+  #ifdef WITH_THREAD /* Python build with threading support? */
+  PyEval_InitThreads();
+  #endif
+  #endif
+  /*--- Module creation code ---*/
+  #if PY_MAJOR_VERSION < 3
+  __pyx_m = Py_InitModule4(__Pyx_NAMESTR("pybuffer"), __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m);
+  #else
+  __pyx_m = PyModule_Create(&__pyx_moduledef);
+  #endif
+  if (unlikely(!__pyx_m)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_d);
+  __pyx_b = PyImport_AddModule(__Pyx_NAMESTR(__Pyx_BUILTIN_MODULE_NAME)); if (unlikely(!__pyx_b)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #if CYTHON_COMPILING_IN_PYPY
+  Py_INCREF(__pyx_b);
+  #endif
+  if (__Pyx_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  /*--- Initialize various global constants etc. ---*/
+  if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT)
+  if (__Pyx_init_sys_getdefaultencoding_params() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  if (__pyx_module_is_main_pybuffer) {
+    if (__Pyx_SetAttrString(__pyx_m, "__name__", __pyx_n_s_main) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  }
+  #if PY_MAJOR_VERSION >= 3
+  {
+    PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!PyDict_GetItemString(modules, "pybuffer")) {
+      if (unlikely(PyDict_SetItemString(modules, "pybuffer", __pyx_m) < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+  }
+  #endif
+  /*--- Builtin init code ---*/
+  if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Constants init code ---*/
+  if (unlikely(__Pyx_InitCachedConstants() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Global init code ---*/
+  __pyx_v_8pybuffer_TypeDict = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  /*--- Variable export code ---*/
+  /*--- Function export code ---*/
+  /*--- Type init code ---*/
+  if (PyType_Ready(&__pyx_type_8pybuffer_Buffer) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_8pybuffer_Buffer.tp_print = 0;
+  if (__Pyx_SetAttrString(__pyx_m, "Buffer", (PyObject *)&__pyx_type_8pybuffer_Buffer) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_8pybuffer_Buffer = &__pyx_type_8pybuffer_Buffer;
+  /*--- Type import code ---*/
+  __pyx_ptype_6mpi4py_3MPI_Status = __Pyx_ImportType("mpi4py.MPI", "Status", sizeof(struct PyMPIStatusObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Status)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Datatype = __Pyx_ImportType("mpi4py.MPI", "Datatype", sizeof(struct PyMPIDatatypeObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Datatype)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Request = __Pyx_ImportType("mpi4py.MPI", "Request", sizeof(struct PyMPIRequestObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Request)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Prequest = __Pyx_ImportType("mpi4py.MPI", "Prequest", sizeof(struct PyMPIPrequestObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Prequest)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Grequest = __Pyx_ImportType("mpi4py.MPI", "Grequest", sizeof(struct PyMPIGrequestObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Grequest)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Op = __Pyx_ImportType("mpi4py.MPI", "Op", sizeof(struct PyMPIOpObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Op)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Group = __Pyx_ImportType("mpi4py.MPI", "Group", sizeof(struct PyMPIGroupObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Group)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Info = __Pyx_ImportType("mpi4py.MPI", "Info", sizeof(struct PyMPIInfoObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Info)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Errhandler = __Pyx_ImportType("mpi4py.MPI", "Errhandler", sizeof(struct PyMPIErrhandlerObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Errhandler)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Comm = __Pyx_ImportType("mpi4py.MPI", "Comm", sizeof(struct PyMPICommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Comm)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Intracomm = __Pyx_ImportType("mpi4py.MPI", "Intracomm", sizeof(struct PyMPIIntracommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Intracomm)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Cartcomm = __Pyx_ImportType("mpi4py.MPI", "Cartcomm", sizeof(struct PyMPICartcommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Cartcomm)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Graphcomm = __Pyx_ImportType("mpi4py.MPI", "Graphcomm", sizeof(struct PyMPIGraphcommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Graphcomm)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Distgraphcomm = __Pyx_ImportType("mpi4py.MPI", "Distgraphcomm", sizeof(struct PyMPIDistgraphcommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Distgraphcomm)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Intercomm = __Pyx_ImportType("mpi4py.MPI", "Intercomm", sizeof(struct PyMPIIntercommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Intercomm)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Win = __Pyx_ImportType("mpi4py.MPI", "Win", sizeof(struct PyMPIWinObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Win)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_File = __Pyx_ImportType("mpi4py.MPI", "File", sizeof(struct PyMPIFileObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_File)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Variable import code ---*/
+  /*--- Function import code ---*/
+  /*--- Execution code ---*/
+
+  /* "pybuffer.pyx":10
+ * from libc.stdlib cimport malloc, free
+ * 
+ * from mpi4py import MPI             # <<<<<<<<<<<<<<
+ * 
+ * ###########################################################
+ */
+  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_n_s_MPI);
+  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_MPI);
+  __Pyx_GIVEREF(__pyx_n_s_MPI);
+  __pyx_t_2 = __Pyx_Import(__pyx_n_s_mpi4py, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_MPI, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pybuffer.pyx":14
+ * ###########################################################
+ * 
+ * cdef dict TypeDict = {             # <<<<<<<<<<<<<<
+ *     "?" : MPI.C_BOOL,
+ *     "c" : MPI.CHAR,
+ */
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+
+  /* "pybuffer.pyx":15
+ * 
+ * cdef dict TypeDict = {
+ *     "?" : MPI.C_BOOL,             # <<<<<<<<<<<<<<
+ *     "c" : MPI.CHAR,
+ *     "b" : MPI.SIGNED_CHAR,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_C_BOOL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_kp_s__2, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":16
+ * cdef dict TypeDict = {
+ *     "?" : MPI.C_BOOL,
+ *     "c" : MPI.CHAR,             # <<<<<<<<<<<<<<
+ *     "b" : MPI.SIGNED_CHAR,
+ *     "h" : MPI.SHORT,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_CHAR); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_c, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":17
+ *     "?" : MPI.C_BOOL,
+ *     "c" : MPI.CHAR,
+ *     "b" : MPI.SIGNED_CHAR,             # <<<<<<<<<<<<<<
+ *     "h" : MPI.SHORT,
+ *     "i" : MPI.INT,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_SIGNED_CHAR); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_b, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":18
+ *     "c" : MPI.CHAR,
+ *     "b" : MPI.SIGNED_CHAR,
+ *     "h" : MPI.SHORT,             # <<<<<<<<<<<<<<
+ *     "i" : MPI.INT,
+ *     "l" : MPI.LONG,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_SHORT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_h, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":19
+ *     "b" : MPI.SIGNED_CHAR,
+ *     "h" : MPI.SHORT,
+ *     "i" : MPI.INT,             # <<<<<<<<<<<<<<
+ *     "l" : MPI.LONG,
+ *     "q" : MPI.LONG_LONG,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_INT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_i, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":20
+ *     "h" : MPI.SHORT,
+ *     "i" : MPI.INT,
+ *     "l" : MPI.LONG,             # <<<<<<<<<<<<<<
+ *     "q" : MPI.LONG_LONG,
+ *     "p" : MPI.AINT,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_LONG); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_l, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":21
+ *     "i" : MPI.INT,
+ *     "l" : MPI.LONG,
+ *     "q" : MPI.LONG_LONG,             # <<<<<<<<<<<<<<
+ *     "p" : MPI.AINT,
+ *     "B" : MPI.UNSIGNED_CHAR,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_LONG_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_q, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":22
+ *     "l" : MPI.LONG,
+ *     "q" : MPI.LONG_LONG,
+ *     "p" : MPI.AINT,             # <<<<<<<<<<<<<<
+ *     "B" : MPI.UNSIGNED_CHAR,
+ *     "H" : MPI.UNSIGNED_SHORT,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_AINT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_p, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":23
+ *     "q" : MPI.LONG_LONG,
+ *     "p" : MPI.AINT,
+ *     "B" : MPI.UNSIGNED_CHAR,             # <<<<<<<<<<<<<<
+ *     "H" : MPI.UNSIGNED_SHORT,
+ *     "I" : MPI.UNSIGNED,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_UNSIGNED_CHAR); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_B, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":24
+ *     "p" : MPI.AINT,
+ *     "B" : MPI.UNSIGNED_CHAR,
+ *     "H" : MPI.UNSIGNED_SHORT,             # <<<<<<<<<<<<<<
+ *     "I" : MPI.UNSIGNED,
+ *     "L" : MPI.UNSIGNED_LONG,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_UNSIGNED_SHORT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_H, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":25
+ *     "B" : MPI.UNSIGNED_CHAR,
+ *     "H" : MPI.UNSIGNED_SHORT,
+ *     "I" : MPI.UNSIGNED,             # <<<<<<<<<<<<<<
+ *     "L" : MPI.UNSIGNED_LONG,
+ *     "Q" : MPI.UNSIGNED_LONG_LONG,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_UNSIGNED); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_I, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":26
+ *     "H" : MPI.UNSIGNED_SHORT,
+ *     "I" : MPI.UNSIGNED,
+ *     "L" : MPI.UNSIGNED_LONG,             # <<<<<<<<<<<<<<
+ *     "Q" : MPI.UNSIGNED_LONG_LONG,
+ *     "f" : MPI.FLOAT,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_UNSIGNED_LONG); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_L, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":27
+ *     "I" : MPI.UNSIGNED,
+ *     "L" : MPI.UNSIGNED_LONG,
+ *     "Q" : MPI.UNSIGNED_LONG_LONG,             # <<<<<<<<<<<<<<
+ *     "f" : MPI.FLOAT,
+ *     "d" : MPI.DOUBLE,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_UNSIGNED_LONG_LONG); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_Q, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":28
+ *     "L" : MPI.UNSIGNED_LONG,
+ *     "Q" : MPI.UNSIGNED_LONG_LONG,
+ *     "f" : MPI.FLOAT,             # <<<<<<<<<<<<<<
+ *     "d" : MPI.DOUBLE,
+ *     "g" : MPI.LONG_DOUBLE,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_FLOAT); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_f, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":29
+ *     "Q" : MPI.UNSIGNED_LONG_LONG,
+ *     "f" : MPI.FLOAT,
+ *     "d" : MPI.DOUBLE,             # <<<<<<<<<<<<<<
+ *     "g" : MPI.LONG_DOUBLE,
+ *     "Zf": MPI.C_FLOAT_COMPLEX,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_DOUBLE); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_d, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":30
+ *     "f" : MPI.FLOAT,
+ *     "d" : MPI.DOUBLE,
+ *     "g" : MPI.LONG_DOUBLE,             # <<<<<<<<<<<<<<
+ *     "Zf": MPI.C_FLOAT_COMPLEX,
+ *     "Zd": MPI.C_DOUBLE_COMPLEX,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_LONG_DOUBLE); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_g, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":31
+ *     "d" : MPI.DOUBLE,
+ *     "g" : MPI.LONG_DOUBLE,
+ *     "Zf": MPI.C_FLOAT_COMPLEX,             # <<<<<<<<<<<<<<
+ *     "Zd": MPI.C_DOUBLE_COMPLEX,
+ *     "Zg": MPI.C_LONG_DOUBLE_COMPLEX,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_C_FLOAT_COMPLEX); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_Zf, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":32
+ *     "g" : MPI.LONG_DOUBLE,
+ *     "Zf": MPI.C_FLOAT_COMPLEX,
+ *     "Zd": MPI.C_DOUBLE_COMPLEX,             # <<<<<<<<<<<<<<
+ *     "Zg": MPI.C_LONG_DOUBLE_COMPLEX,
+ *     "F" : MPI.C_FLOAT_COMPLEX,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_C_DOUBLE_COMPLEX); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_Zd, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":33
+ *     "Zf": MPI.C_FLOAT_COMPLEX,
+ *     "Zd": MPI.C_DOUBLE_COMPLEX,
+ *     "Zg": MPI.C_LONG_DOUBLE_COMPLEX,             # <<<<<<<<<<<<<<
+ *     "F" : MPI.C_FLOAT_COMPLEX,
+ *     "D" : MPI.C_DOUBLE_COMPLEX,
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_C_LONG_DOUBLE_COMPLEX); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_Zg, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":34
+ *     "Zd": MPI.C_DOUBLE_COMPLEX,
+ *     "Zg": MPI.C_LONG_DOUBLE_COMPLEX,
+ *     "F" : MPI.C_FLOAT_COMPLEX,             # <<<<<<<<<<<<<<
+ *     "D" : MPI.C_DOUBLE_COMPLEX,
+ *     "G" : MPI.C_LONG_DOUBLE_COMPLEX,
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_C_FLOAT_COMPLEX); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_F, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pybuffer.pyx":35
+ *     "Zg": MPI.C_LONG_DOUBLE_COMPLEX,
+ *     "F" : MPI.C_FLOAT_COMPLEX,
+ *     "D" : MPI.C_DOUBLE_COMPLEX,             # <<<<<<<<<<<<<<
+ *     "G" : MPI.C_LONG_DOUBLE_COMPLEX,
+ * }
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_C_DOUBLE_COMPLEX); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_D, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "pybuffer.pyx":36
+ *     "F" : MPI.C_FLOAT_COMPLEX,
+ *     "D" : MPI.C_DOUBLE_COMPLEX,
+ *     "G" : MPI.C_LONG_DOUBLE_COMPLEX,             # <<<<<<<<<<<<<<
+ * }
+ * 
+ */
+  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_C_LONG_DOUBLE_COMPLEX); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_G, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_XGOTREF(__pyx_v_8pybuffer_TypeDict);
+  __Pyx_DECREF_SET(__pyx_v_8pybuffer_TypeDict, ((PyObject*)__pyx_t_2));
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "pybuffer.pyx":53
+ *     return PyUnicodeString_FromString(pybuf.format)
+ * 
+ * cdef int bufflags = PyBUF_ANY_CONTIGUOUS | PyBUF_WRITABLE | PyBUF_FORMAT             # <<<<<<<<<<<<<<
+ * 
+ * cdef class Buffer(object):
+ */
+  __pyx_v_8pybuffer_bufflags = ((PyBUF_ANY_CONTIGUOUS | PyBUF_WRITABLE) | PyBUF_FORMAT);
+
+  /* "pybuffer.pyx":1
+ * #             # <<<<<<<<<<<<<<
+ * # distutils: language = c++
+ * #
+ */
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  if (__pyx_m) {
+    __Pyx_AddTraceback("init pybuffer", __pyx_clineno, __pyx_lineno, __pyx_filename);
+    Py_DECREF(__pyx_m); __pyx_m = 0;
+  } else if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_ImportError, "init pybuffer");
+  }
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  #if PY_MAJOR_VERSION < 3
+  return;
+  #else
+  return __pyx_m;
+  #endif
+}
+
+/* Runtime support code */
+#if CYTHON_REFNANNY
+static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
+    PyObject *m = NULL, *p = NULL;
+    void *r = NULL;
+    m = PyImport_ImportModule((char *)modname);
+    if (!m) goto end;
+    p = PyObject_GetAttrString(m, (char *)"RefNannyAPI");
+    if (!p) goto end;
+    r = PyLong_AsVoidPtr(p);
+end:
+    Py_XDECREF(p);
+    Py_XDECREF(m);
+    return (__Pyx_RefNannyAPIStruct *)r;
+}
+#endif /* CYTHON_REFNANNY */
+
+static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
+    PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name);
+    if (unlikely(!result)) {
+        PyErr_Format(PyExc_NameError,
+#if PY_MAJOR_VERSION >= 3
+            "name '%U' is not defined", name);
+#else
+            "name '%.200s' is not defined", PyString_AS_STRING(name));
+#endif
+    }
+    return result;
+}
+
+static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyThreadState *tstate = PyThreadState_GET();
+    *type = tstate->exc_type;
+    *value = tstate->exc_value;
+    *tb = tstate->exc_traceback;
+    Py_XINCREF(*type);
+    Py_XINCREF(*value);
+    Py_XINCREF(*tb);
+#else
+    PyErr_GetExcInfo(type, value, tb);
+#endif
+}
+static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+    PyThreadState *tstate = PyThreadState_GET();
+    tmp_type = tstate->exc_type;
+    tmp_value = tstate->exc_value;
+    tmp_tb = tstate->exc_traceback;
+    tstate->exc_type = type;
+    tstate->exc_value = value;
+    tstate->exc_traceback = tb;
+    Py_XDECREF(tmp_type);
+    Py_XDECREF(tmp_value);
+    Py_XDECREF(tmp_tb);
+#else
+    PyErr_SetExcInfo(type, value, tb);
+#endif
+}
+
+static void __Pyx_RaiseDoubleKeywordsError(
+    const char* func_name,
+    PyObject* kw_name)
+{
+    PyErr_Format(PyExc_TypeError,
+        #if PY_MAJOR_VERSION >= 3
+        "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
+        #else
+        "%s() got multiple values for keyword argument '%s'", func_name,
+        PyString_AsString(kw_name));
+        #endif
+}
+
+static int __Pyx_ParseOptionalKeywords(
+    PyObject *kwds,
+    PyObject **argnames[],
+    PyObject *kwds2,
+    PyObject *values[],
+    Py_ssize_t num_pos_args,
+    const char* function_name)
+{
+    PyObject *key = 0, *value = 0;
+    Py_ssize_t pos = 0;
+    PyObject*** name;
+    PyObject*** first_kw_arg = argnames + num_pos_args;
+    while (PyDict_Next(kwds, &pos, &key, &value)) {
+        name = first_kw_arg;
+        while (*name && (**name != key)) name++;
+        if (*name) {
+            values[name-argnames] = value;
+            continue;
+        }
+        name = first_kw_arg;
+        #if PY_MAJOR_VERSION < 3
+        if (likely(PyString_CheckExact(key)) || likely(PyString_Check(key))) {
+            while (*name) {
+                if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key))
+                        && _PyString_Eq(**name, key)) {
+                    values[name-argnames] = value;
+                    break;
+                }
+                name++;
+            }
+            if (*name) continue;
+            else {
+                PyObject*** argname = argnames;
+                while (argname != first_kw_arg) {
+                    if ((**argname == key) || (
+                            (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key))
+                             && _PyString_Eq(**argname, key))) {
+                        goto arg_passed_twice;
+                    }
+                    argname++;
+                }
+            }
+        } else
+        #endif
+        if (likely(PyUnicode_Check(key))) {
+            while (*name) {
+                int cmp = (**name == key) ? 0 :
+                #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
+                    (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 :
+                #endif
+                    PyUnicode_Compare(**name, key);
+                if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
+                if (cmp == 0) {
+                    values[name-argnames] = value;
+                    break;
+                }
+                name++;
+            }
+            if (*name) continue;
+            else {
+                PyObject*** argname = argnames;
+                while (argname != first_kw_arg) {
+                    int cmp = (**argname == key) ? 0 :
+                    #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
+                        (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 :
+                    #endif
+                        PyUnicode_Compare(**argname, key);
+                    if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
+                    if (cmp == 0) goto arg_passed_twice;
+                    argname++;
+                }
+            }
+        } else
+            goto invalid_keyword_type;
+        if (kwds2) {
+            if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
+        } else {
+            goto invalid_keyword;
+        }
+    }
+    return 0;
+arg_passed_twice:
+    __Pyx_RaiseDoubleKeywordsError(function_name, key);
+    goto bad;
+invalid_keyword_type:
+    PyErr_Format(PyExc_TypeError,
+        "%.200s() keywords must be strings", function_name);
+    goto bad;
+invalid_keyword:
+    PyErr_Format(PyExc_TypeError,
+    #if PY_MAJOR_VERSION < 3
+        "%.200s() got an unexpected keyword argument '%.200s'",
+        function_name, PyString_AsString(key));
+    #else
+        "%s() got an unexpected keyword argument '%U'",
+        function_name, key);
+    #endif
+bad:
+    return -1;
+}
+
+static void __Pyx_RaiseArgtupleInvalid(
+    const char* func_name,
+    int exact,
+    Py_ssize_t num_min,
+    Py_ssize_t num_max,
+    Py_ssize_t num_found)
+{
+    Py_ssize_t num_expected;
+    const char *more_or_less;
+    if (num_found < num_min) {
+        num_expected = num_min;
+        more_or_less = "at least";
+    } else {
+        num_expected = num_max;
+        more_or_less = "at most";
+    }
+    if (exact) {
+        more_or_less = "exactly";
+    }
+    PyErr_Format(PyExc_TypeError,
+                 "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)",
+                 func_name, more_or_less, num_expected,
+                 (num_expected == 1) ? "" : "s", num_found);
+}
+
+static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+    PyThreadState *tstate = PyThreadState_GET();
+    tmp_type = tstate->curexc_type;
+    tmp_value = tstate->curexc_value;
+    tmp_tb = tstate->curexc_traceback;
+    tstate->curexc_type = type;
+    tstate->curexc_value = value;
+    tstate->curexc_traceback = tb;
+    Py_XDECREF(tmp_type);
+    Py_XDECREF(tmp_value);
+    Py_XDECREF(tmp_tb);
+#else
+    PyErr_Restore(type, value, tb);
+#endif
+}
+static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyThreadState *tstate = PyThreadState_GET();
+    *type = tstate->curexc_type;
+    *value = tstate->curexc_value;
+    *tb = tstate->curexc_traceback;
+    tstate->curexc_type = 0;
+    tstate->curexc_value = 0;
+    tstate->curexc_traceback = 0;
+#else
+    PyErr_Fetch(type, value, tb);
+#endif
+}
+
+#if PY_MAJOR_VERSION < 3
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
+                        CYTHON_UNUSED PyObject *cause) {
+    Py_XINCREF(type);
+    if (!value || value == Py_None)
+        value = NULL;
+    else
+        Py_INCREF(value);
+    if (!tb || tb == Py_None)
+        tb = NULL;
+    else {
+        Py_INCREF(tb);
+        if (!PyTraceBack_Check(tb)) {
+            PyErr_SetString(PyExc_TypeError,
+                "raise: arg 3 must be a traceback or None");
+            goto raise_error;
+        }
+    }
+    #if PY_VERSION_HEX < 0x02050000
+    if (PyClass_Check(type)) {
+    #else
+    if (PyType_Check(type)) {
+    #endif
+#if CYTHON_COMPILING_IN_PYPY
+        if (!value) {
+            Py_INCREF(Py_None);
+            value = Py_None;
+        }
+#endif
+        PyErr_NormalizeException(&type, &value, &tb);
+    } else {
+        if (value) {
+            PyErr_SetString(PyExc_TypeError,
+                "instance exception may not have a separate value");
+            goto raise_error;
+        }
+        value = type;
+        #if PY_VERSION_HEX < 0x02050000
+        if (PyInstance_Check(type)) {
+            type = (PyObject*) ((PyInstanceObject*)type)->in_class;
+            Py_INCREF(type);
+        } else {
+            type = 0;
+            PyErr_SetString(PyExc_TypeError,
+                "raise: exception must be an old-style class or instance");
+            goto raise_error;
+        }
+        #else
+        type = (PyObject*) Py_TYPE(type);
+        Py_INCREF(type);
+        if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
+            PyErr_SetString(PyExc_TypeError,
+                "raise: exception class must be a subclass of BaseException");
+            goto raise_error;
+        }
+        #endif
+    }
+    __Pyx_ErrRestore(type, value, tb);
+    return;
+raise_error:
+    Py_XDECREF(value);
+    Py_XDECREF(type);
+    Py_XDECREF(tb);
+    return;
+}
+#else /* Python 3+ */
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
+    PyObject* owned_instance = NULL;
+    if (tb == Py_None) {
+        tb = 0;
+    } else if (tb && !PyTraceBack_Check(tb)) {
+        PyErr_SetString(PyExc_TypeError,
+            "raise: arg 3 must be a traceback or None");
+        goto bad;
+    }
+    if (value == Py_None)
+        value = 0;
+    if (PyExceptionInstance_Check(type)) {
+        if (value) {
+            PyErr_SetString(PyExc_TypeError,
+                "instance exception may not have a separate value");
+            goto bad;
+        }
+        value = type;
+        type = (PyObject*) Py_TYPE(value);
+    } else if (PyExceptionClass_Check(type)) {
+        PyObject *instance_class = NULL;
+        if (value && PyExceptionInstance_Check(value)) {
+            instance_class = (PyObject*) Py_TYPE(value);
+            if (instance_class != type) {
+                if (PyObject_IsSubclass(instance_class, type)) {
+                    type = instance_class;
+                } else {
+                    instance_class = NULL;
+                }
+            }
+        }
+        if (!instance_class) {
+            PyObject *args;
+            if (!value)
+                args = PyTuple_New(0);
+            else if (PyTuple_Check(value)) {
+                Py_INCREF(value);
+                args = value;
+            } else
+                args = PyTuple_Pack(1, value);
+            if (!args)
+                goto bad;
+            owned_instance = PyObject_Call(type, args, NULL);
+            Py_DECREF(args);
+            if (!owned_instance)
+                goto bad;
+            value = owned_instance;
+            if (!PyExceptionInstance_Check(value)) {
+                PyErr_Format(PyExc_TypeError,
+                             "calling %R should have returned an instance of "
+                             "BaseException, not %R",
+                             type, Py_TYPE(value));
+                goto bad;
+            }
+        }
+    } else {
+        PyErr_SetString(PyExc_TypeError,
+            "raise: exception class must be a subclass of BaseException");
+        goto bad;
+    }
+#if PY_VERSION_HEX >= 0x03030000
+    if (cause) {
+#else
+    if (cause && cause != Py_None) {
+#endif
+        PyObject *fixed_cause;
+        if (cause == Py_None) {
+            fixed_cause = NULL;
+        } else if (PyExceptionClass_Check(cause)) {
+            fixed_cause = PyObject_CallObject(cause, NULL);
+            if (fixed_cause == NULL)
+                goto bad;
+        } else if (PyExceptionInstance_Check(cause)) {
+            fixed_cause = cause;
+            Py_INCREF(fixed_cause);
+        } else {
+            PyErr_SetString(PyExc_TypeError,
+                            "exception causes must derive from "
+                            "BaseException");
+            goto bad;
+        }
+        PyException_SetCause(value, fixed_cause);
+    }
+    PyErr_SetObject(type, value);
+    if (tb) {
+        PyThreadState *tstate = PyThreadState_GET();
+        PyObject* tmp_tb = tstate->curexc_traceback;
+        if (tb != tmp_tb) {
+            Py_INCREF(tb);
+            tstate->curexc_traceback = tb;
+            Py_XDECREF(tmp_tb);
+        }
+    }
+bad:
+    Py_XDECREF(owned_instance);
+    return;
+}
+#endif
+
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
+    if (unlikely(!type)) {
+        PyErr_SetString(PyExc_SystemError, "Missing type object");
+        return 0;
+    }
+    if (likely(PyObject_TypeCheck(obj, type)))
+        return 1;
+    PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
+                 Py_TYPE(obj)->tp_name, type->tp_name);
+    return 0;
+}
+
+static CYTHON_INLINE Py_ssize_t __Pyx_div_Py_ssize_t(Py_ssize_t a, Py_ssize_t b) {
+    Py_ssize_t q = a / b;
+    Py_ssize_t r = a - q*b;
+    q -= ((r != 0) & ((r ^ b) < 0));
+    return q;
+}
+
+static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) {
+    PyObject* value = __Pyx_PyObject_GetAttrStr(module, name);
+    if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+        PyErr_Format(PyExc_ImportError,
+        #if PY_MAJOR_VERSION < 3
+            "cannot import name %.230s", PyString_AS_STRING(name));
+        #else
+            "cannot import name %S", name);
+        #endif
+    }
+    return value;
+}
+
+static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) {
+    PyObject *result;
+#if CYTHON_COMPILING_IN_CPYTHON
+    result = PyDict_GetItem(__pyx_d, name);
+    if (result) {
+        Py_INCREF(result);
+    } else {
+#else
+    result = PyObject_GetItem(__pyx_d, name);
+    if (!result) {
+        PyErr_Clear();
+#endif
+        result = __Pyx_GetBuiltinName(name);
+    }
+    return result;
+}
+
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
+    PyObject *empty_list = 0;
+    PyObject *module = 0;
+    PyObject *global_dict = 0;
+    PyObject *empty_dict = 0;
+    PyObject *list;
+    #if PY_VERSION_HEX < 0x03030000
+    PyObject *py_import;
+    py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import);
+    if (!py_import)
+        goto bad;
+    #endif
+    if (from_list)
+        list = from_list;
+    else {
+        empty_list = PyList_New(0);
+        if (!empty_list)
+            goto bad;
+        list = empty_list;
+    }
+    global_dict = PyModule_GetDict(__pyx_m);
+    if (!global_dict)
+        goto bad;
+    empty_dict = PyDict_New();
+    if (!empty_dict)
+        goto bad;
+    #if PY_VERSION_HEX >= 0x02050000
+    {
+        #if PY_MAJOR_VERSION >= 3
+        if (level == -1) {
+            if (strchr(__Pyx_MODULE_NAME, '.')) {
+                #if PY_VERSION_HEX < 0x03030000
+                PyObject *py_level = PyInt_FromLong(1);
+                if (!py_level)
+                    goto bad;
+                module = PyObject_CallFunctionObjArgs(py_import,
+                    name, global_dict, empty_dict, list, py_level, NULL);
+                Py_DECREF(py_level);
+                #else
+                module = PyImport_ImportModuleLevelObject(
+                    name, global_dict, empty_dict, list, 1);
+                #endif
+                if (!module) {
+                    if (!PyErr_ExceptionMatches(PyExc_ImportError))
+                        goto bad;
+                    PyErr_Clear();
+                }
+            }
+            level = 0; /* try absolute import on failure */
+        }
+        #endif
+        if (!module) {
+            #if PY_VERSION_HEX < 0x03030000
+            PyObject *py_level = PyInt_FromLong(level);
+            if (!py_level)
+                goto bad;
+            module = PyObject_CallFunctionObjArgs(py_import,
+                name, global_dict, empty_dict, list, py_level, NULL);
+            Py_DECREF(py_level);
+            #else
+            module = PyImport_ImportModuleLevelObject(
+                name, global_dict, empty_dict, list, level);
+            #endif
+        }
+    }
+    #else
+    if (level>0) {
+        PyErr_SetString(PyExc_RuntimeError, "Relative import is not supported for Python <=2.4.");
+        goto bad;
+    }
+    module = PyObject_CallFunctionObjArgs(py_import,
+        name, global_dict, empty_dict, list, NULL);
+    #endif
+bad:
+    #if PY_VERSION_HEX < 0x03030000
+    Py_XDECREF(py_import);
+    #endif
+    Py_XDECREF(empty_list);
+    Py_XDECREF(empty_dict);
+    return module;
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) {
+    const long neg_one = (long) -1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (is_unsigned) {
+        if (sizeof(long) < sizeof(long)) {
+            return PyInt_FromLong((long) value);
+        } else if (sizeof(long) <= sizeof(unsigned long)) {
+            return PyLong_FromUnsignedLong((unsigned long) value);
+        } else if (sizeof(long) <= sizeof(unsigned long long)) {
+            return PyLong_FromUnsignedLongLong((unsigned long long) value);
+        }
+    } else {
+        if (sizeof(long) <= sizeof(long)) {
+            return PyInt_FromLong((long) value);
+        } else if (sizeof(long) <= sizeof(long long)) {
+            return PyLong_FromLongLong((long long) value);
+        }
+    }
+    {
+        int one = 1; int little = (int)*(unsigned char *)&one;
+        unsigned char *bytes = (unsigned char *)&value;
+        return _PyLong_FromByteArray(bytes, sizeof(long),
+                                     little, !is_unsigned);
+    }
+}
+
+#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func)             \
+    {                                                                     \
+        func_type value = func(x);                                        \
+        if (sizeof(target_type) < sizeof(func_type)) {                    \
+            if (unlikely(value != (func_type) (target_type) value)) {     \
+                func_type zero = 0;                                       \
+                PyErr_SetString(PyExc_OverflowError,                      \
+                    (is_unsigned && unlikely(value < zero)) ?             \
+                    "can't convert negative value to " #target_type :     \
+                    "value too large to convert to " #target_type);       \
+                return (target_type) -1;                                  \
+            }                                                             \
+        }                                                                 \
+        return (target_type) value;                                       \
+    }
+
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+  #include "longintrepr.h"
+ #endif
+#endif
+static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) {
+    const long neg_one = (long) -1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_MAJOR_VERSION < 3
+    if (likely(PyInt_Check(x))) {
+        if (sizeof(long) < sizeof(long)) {
+            __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG)
+        } else {
+            long val = PyInt_AS_LONG(x);
+            if (is_unsigned && unlikely(val < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to long");
+                return (long) -1;
+            }
+            return (long) val;
+        }
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(long)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return (long) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+ #endif
+#endif
+            if (unlikely(Py_SIZE(x) < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to long");
+                return (long) -1;
+            }
+            if (sizeof(long) <= sizeof(unsigned long)) {
+                __PYX_VERIFY_RETURN_INT(long, unsigned long, PyLong_AsUnsignedLong)
+            } else if (sizeof(long) <= sizeof(unsigned long long)) {
+                __PYX_VERIFY_RETURN_INT(long, unsigned long long, PyLong_AsUnsignedLongLong)
+            }
+        } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(long)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return +(long) ((PyLongObject*)x)->ob_digit[0];
+                    case -1: return -(long) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+ #endif
+#endif
+            if (sizeof(long) <= sizeof(long)) {
+                __PYX_VERIFY_RETURN_INT(long, long, PyLong_AsLong)
+            } else if (sizeof(long) <= sizeof(long long)) {
+                __PYX_VERIFY_RETURN_INT(long, long long, PyLong_AsLongLong)
+            }
+        }
+        {
+#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
+            PyErr_SetString(PyExc_RuntimeError,
+                            "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
+#else
+            long val;
+            PyObject *v = __Pyx_PyNumber_Int(x);
+ #if PY_MAJOR_VERSION < 3
+            if (likely(v) && !PyLong_Check(v)) {
+                PyObject *tmp = v;
+                v = PyNumber_Long(tmp);
+                Py_DECREF(tmp);
+            }
+ #endif
+            if (likely(v)) {
+                int one = 1; int is_little = (int)*(unsigned char *)&one;
+                unsigned char *bytes = (unsigned char *)&val;
+                int ret = _PyLong_AsByteArray((PyLongObject *)v,
+                                              bytes, sizeof(val),
+                                              is_little, !is_unsigned);
+                Py_DECREF(v);
+                if (likely(!ret))
+                    return val;
+            }
+#endif
+            return (long) -1;
+        }
+    } else {
+        long val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (long) -1;
+        val = __Pyx_PyInt_As_long(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+  #include "longintrepr.h"
+ #endif
+#endif
+static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) {
+    const int neg_one = (int) -1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_MAJOR_VERSION < 3
+    if (likely(PyInt_Check(x))) {
+        if (sizeof(int) < sizeof(long)) {
+            __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG)
+        } else {
+            long val = PyInt_AS_LONG(x);
+            if (is_unsigned && unlikely(val < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to int");
+                return (int) -1;
+            }
+            return (int) val;
+        }
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(int)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return (int) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+ #endif
+#endif
+            if (unlikely(Py_SIZE(x) < 0)) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "can't convert negative value to int");
+                return (int) -1;
+            }
+            if (sizeof(int) <= sizeof(unsigned long)) {
+                __PYX_VERIFY_RETURN_INT(int, unsigned long, PyLong_AsUnsignedLong)
+            } else if (sizeof(int) <= sizeof(unsigned long long)) {
+                __PYX_VERIFY_RETURN_INT(int, unsigned long long, PyLong_AsUnsignedLongLong)
+            }
+        } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(int)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return +(int) ((PyLongObject*)x)->ob_digit[0];
+                    case -1: return -(int) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+ #endif
+#endif
+            if (sizeof(int) <= sizeof(long)) {
+                __PYX_VERIFY_RETURN_INT(int, long, PyLong_AsLong)
+            } else if (sizeof(int) <= sizeof(long long)) {
+                __PYX_VERIFY_RETURN_INT(int, long long, PyLong_AsLongLong)
+            }
+        }
+        {
+#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
+            PyErr_SetString(PyExc_RuntimeError,
+                            "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
+#else
+            int val;
+            PyObject *v = __Pyx_PyNumber_Int(x);
+ #if PY_MAJOR_VERSION < 3
+            if (likely(v) && !PyLong_Check(v)) {
+                PyObject *tmp = v;
+                v = PyNumber_Long(tmp);
+                Py_DECREF(tmp);
+            }
+ #endif
+            if (likely(v)) {
+                int one = 1; int is_little = (int)*(unsigned char *)&one;
+                unsigned char *bytes = (unsigned char *)&val;
+                int ret = _PyLong_AsByteArray((PyLongObject *)v,
+                                              bytes, sizeof(val),
+                                              is_little, !is_unsigned);
+                Py_DECREF(v);
+                if (likely(!ret))
+                    return val;
+            }
+#endif
+            return (int) -1;
+        }
+    } else {
+        int val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (int) -1;
+        val = __Pyx_PyInt_As_int(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+}
+
+static int __Pyx_check_binary_version(void) {
+    char ctversion[4], rtversion[4];
+    PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION);
+    PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion());
+    if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) {
+        char message[200];
+        PyOS_snprintf(message, sizeof(message),
+                      "compiletime version %s of module '%.100s' "
+                      "does not match runtime version %s",
+                      ctversion, __Pyx_MODULE_NAME, rtversion);
+        #if PY_VERSION_HEX < 0x02050000
+        return PyErr_Warn(NULL, message);
+        #else
+        return PyErr_WarnEx(NULL, message, 1);
+        #endif
+    }
+    return 0;
+}
+
+#ifndef __PYX_HAVE_RT_ImportModule
+#define __PYX_HAVE_RT_ImportModule
+static PyObject *__Pyx_ImportModule(const char *name) {
+    PyObject *py_name = 0;
+    PyObject *py_module = 0;
+    py_name = __Pyx_PyIdentifier_FromString(name);
+    if (!py_name)
+        goto bad;
+    py_module = PyImport_Import(py_name);
+    Py_DECREF(py_name);
+    return py_module;
+bad:
+    Py_XDECREF(py_name);
+    return 0;
+}
+#endif
+
+#ifndef __PYX_HAVE_RT_ImportType
+#define __PYX_HAVE_RT_ImportType
+static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name,
+    size_t size, int strict)
+{
+    PyObject *py_module = 0;
+    PyObject *result = 0;
+    PyObject *py_name = 0;
+    char warning[200];
+    Py_ssize_t basicsize;
+#ifdef Py_LIMITED_API
+    PyObject *py_basicsize;
+#endif
+    py_module = __Pyx_ImportModule(module_name);
+    if (!py_module)
+        goto bad;
+    py_name = __Pyx_PyIdentifier_FromString(class_name);
+    if (!py_name)
+        goto bad;
+    result = PyObject_GetAttr(py_module, py_name);
+    Py_DECREF(py_name);
+    py_name = 0;
+    Py_DECREF(py_module);
+    py_module = 0;
+    if (!result)
+        goto bad;
+    if (!PyType_Check(result)) {
+        PyErr_Format(PyExc_TypeError,
+            "%.200s.%.200s is not a type object",
+            module_name, class_name);
+        goto bad;
+    }
+#ifndef Py_LIMITED_API
+    basicsize = ((PyTypeObject *)result)->tp_basicsize;
+#else
+    py_basicsize = PyObject_GetAttrString(result, "__basicsize__");
+    if (!py_basicsize)
+        goto bad;
+    basicsize = PyLong_AsSsize_t(py_basicsize);
+    Py_DECREF(py_basicsize);
+    py_basicsize = 0;
+    if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred())
+        goto bad;
+#endif
+    if (!strict && (size_t)basicsize > size) {
+        PyOS_snprintf(warning, sizeof(warning),
+            "%s.%s size changed, may indicate binary incompatibility",
+            module_name, class_name);
+        #if PY_VERSION_HEX < 0x02050000
+        if (PyErr_Warn(NULL, warning) < 0) goto bad;
+        #else
+        if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad;
+        #endif
+    }
+    else if ((size_t)basicsize != size) {
+        PyErr_Format(PyExc_ValueError,
+            "%.200s.%.200s has the wrong size, try recompiling",
+            module_name, class_name);
+        goto bad;
+    }
+    return (PyTypeObject *)result;
+bad:
+    Py_XDECREF(py_module);
+    Py_XDECREF(result);
+    return NULL;
+}
+#endif
+
+static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
+    int start = 0, mid = 0, end = count - 1;
+    if (end >= 0 && code_line > entries[end].code_line) {
+        return count;
+    }
+    while (start < end) {
+        mid = (start + end) / 2;
+        if (code_line < entries[mid].code_line) {
+            end = mid;
+        } else if (code_line > entries[mid].code_line) {
+             start = mid + 1;
+        } else {
+            return mid;
+        }
+    }
+    if (code_line <= entries[mid].code_line) {
+        return mid;
+    } else {
+        return mid + 1;
+    }
+}
+static PyCodeObject *__pyx_find_code_object(int code_line) {
+    PyCodeObject* code_object;
+    int pos;
+    if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) {
+        return NULL;
+    }
+    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
+    if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) {
+        return NULL;
+    }
+    code_object = __pyx_code_cache.entries[pos].code_object;
+    Py_INCREF(code_object);
+    return code_object;
+}
+static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
+    int pos, i;
+    __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries;
+    if (unlikely(!code_line)) {
+        return;
+    }
+    if (unlikely(!entries)) {
+        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry));
+        if (likely(entries)) {
+            __pyx_code_cache.entries = entries;
+            __pyx_code_cache.max_count = 64;
+            __pyx_code_cache.count = 1;
+            entries[0].code_line = code_line;
+            entries[0].code_object = code_object;
+            Py_INCREF(code_object);
+        }
+        return;
+    }
+    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
+    if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) {
+        PyCodeObject* tmp = entries[pos].code_object;
+        entries[pos].code_object = code_object;
+        Py_DECREF(tmp);
+        return;
+    }
+    if (__pyx_code_cache.count == __pyx_code_cache.max_count) {
+        int new_max = __pyx_code_cache.max_count + 64;
+        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc(
+            __pyx_code_cache.entries, new_max*sizeof(__Pyx_CodeObjectCacheEntry));
+        if (unlikely(!entries)) {
+            return;
+        }
+        __pyx_code_cache.entries = entries;
+        __pyx_code_cache.max_count = new_max;
+    }
+    for (i=__pyx_code_cache.count; i>pos; i--) {
+        entries[i] = entries[i-1];
+    }
+    entries[pos].code_line = code_line;
+    entries[pos].code_object = code_object;
+    __pyx_code_cache.count++;
+    Py_INCREF(code_object);
+}
+
+#include "compile.h"
+#include "frameobject.h"
+#include "traceback.h"
+static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
+            const char *funcname, int c_line,
+            int py_line, const char *filename) {
+    PyCodeObject *py_code = 0;
+    PyObject *py_srcfile = 0;
+    PyObject *py_funcname = 0;
+    #if PY_MAJOR_VERSION < 3
+    py_srcfile = PyString_FromString(filename);
+    #else
+    py_srcfile = PyUnicode_FromString(filename);
+    #endif
+    if (!py_srcfile) goto bad;
+    if (c_line) {
+        #if PY_MAJOR_VERSION < 3
+        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        #else
+        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        #endif
+    }
+    else {
+        #if PY_MAJOR_VERSION < 3
+        py_funcname = PyString_FromString(funcname);
+        #else
+        py_funcname = PyUnicode_FromString(funcname);
+        #endif
+    }
+    if (!py_funcname) goto bad;
+    py_code = __Pyx_PyCode_New(
+        0,            /*int argcount,*/
+        0,            /*int kwonlyargcount,*/
+        0,            /*int nlocals,*/
+        0,            /*int stacksize,*/
+        0,            /*int flags,*/
+        __pyx_empty_bytes, /*PyObject *code,*/
+        __pyx_empty_tuple, /*PyObject *consts,*/
+        __pyx_empty_tuple, /*PyObject *names,*/
+        __pyx_empty_tuple, /*PyObject *varnames,*/
+        __pyx_empty_tuple, /*PyObject *freevars,*/
+        __pyx_empty_tuple, /*PyObject *cellvars,*/
+        py_srcfile,   /*PyObject *filename,*/
+        py_funcname,  /*PyObject *name,*/
+        py_line,      /*int firstlineno,*/
+        __pyx_empty_bytes  /*PyObject *lnotab*/
+    );
+    Py_DECREF(py_srcfile);
+    Py_DECREF(py_funcname);
+    return py_code;
+bad:
+    Py_XDECREF(py_srcfile);
+    Py_XDECREF(py_funcname);
+    return NULL;
+}
+static void __Pyx_AddTraceback(const char *funcname, int c_line,
+                               int py_line, const char *filename) {
+    PyCodeObject *py_code = 0;
+    PyObject *py_globals = 0;
+    PyFrameObject *py_frame = 0;
+    py_code = __pyx_find_code_object(c_line ? c_line : py_line);
+    if (!py_code) {
+        py_code = __Pyx_CreateCodeObjectForTraceback(
+            funcname, c_line, py_line, filename);
+        if (!py_code) goto bad;
+        __pyx_insert_code_object(c_line ? c_line : py_line, py_code);
+    }
+    py_globals = PyModule_GetDict(__pyx_m);
+    if (!py_globals) goto bad;
+    py_frame = PyFrame_New(
+        PyThreadState_GET(), /*PyThreadState *tstate,*/
+        py_code,             /*PyCodeObject *code,*/
+        py_globals,          /*PyObject *globals,*/
+        0                    /*PyObject *locals*/
+    );
+    if (!py_frame) goto bad;
+    py_frame->f_lineno = py_line;
+    PyTraceBack_Here(py_frame);
+bad:
+    Py_XDECREF(py_code);
+    Py_XDECREF(py_frame);
+}
+
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
+    while (t->p) {
+        #if PY_MAJOR_VERSION < 3
+        if (t->is_unicode) {
+            *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
+        } else if (t->intern) {
+            *t->p = PyString_InternFromString(t->s);
+        } else {
+            *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
+        }
+        #else  /* Python 3+ has unicode identifiers */
+        if (t->is_unicode | t->is_str) {
+            if (t->intern) {
+                *t->p = PyUnicode_InternFromString(t->s);
+            } else if (t->encoding) {
+                *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
+            } else {
+                *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
+            }
+        } else {
+            *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
+        }
+        #endif
+        if (!*t->p)
+            return -1;
+        ++t;
+    }
+    return 0;
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(char* c_str) {
+    return __Pyx_PyUnicode_FromStringAndSize(c_str, strlen(c_str));
+}
+static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) {
+    Py_ssize_t ignore;
+    return __Pyx_PyObject_AsStringAndSize(o, &ignore);
+}
+static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) {
+#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
+    if (
+#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+            __Pyx_sys_getdefaultencoding_not_ascii &&
+#endif
+            PyUnicode_Check(o)) {
+#if PY_VERSION_HEX < 0x03030000
+        char* defenc_c;
+        PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL);
+        if (!defenc) return NULL;
+        defenc_c = PyBytes_AS_STRING(defenc);
+#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+        {
+            char* end = defenc_c + PyBytes_GET_SIZE(defenc);
+            char* c;
+            for (c = defenc_c; c < end; c++) {
+                if ((unsigned char) (*c) >= 128) {
+                    PyUnicode_AsASCIIString(o);
+                    return NULL;
+                }
+            }
+        }
+#endif /*__PYX_DEFAULT_STRING_ENCODING_IS_ASCII*/
+        *length = PyBytes_GET_SIZE(defenc);
+        return defenc_c;
+#else /* PY_VERSION_HEX < 0x03030000 */
+        if (PyUnicode_READY(o) == -1) return NULL;
+#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+        if (PyUnicode_IS_ASCII(o)) {
+            *length = PyUnicode_GET_DATA_SIZE(o);
+            return PyUnicode_AsUTF8(o);
+        } else {
+            PyUnicode_AsASCIIString(o);
+            return NULL;
+        }
+#else /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII */
+        return PyUnicode_AsUTF8AndSize(o, length);
+#endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII */
+#endif /* PY_VERSION_HEX < 0x03030000 */
+    } else
+#endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII  || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT */
+#if PY_VERSION_HEX >= 0x02060000
+    if (PyByteArray_Check(o)) {
+        *length = PyByteArray_GET_SIZE(o);
+        return PyByteArray_AS_STRING(o);
+    } else
+#endif
+    {
+        char* result;
+        int r = PyBytes_AsStringAndSize(o, &result, length);
+        if (unlikely(r < 0)) {
+            return NULL;
+        } else {
+            return result;
+        }
+    }
+}
+static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
+   int is_true = x == Py_True;
+   if (is_true | (x == Py_False) | (x == Py_None)) return is_true;
+   else return PyObject_IsTrue(x);
+}
+static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
+  PyNumberMethods *m;
+  const char *name = NULL;
+  PyObject *res = NULL;
+#if PY_MAJOR_VERSION < 3
+  if (PyInt_Check(x) || PyLong_Check(x))
+#else
+  if (PyLong_Check(x))
+#endif
+    return Py_INCREF(x), x;
+  m = Py_TYPE(x)->tp_as_number;
+#if PY_MAJOR_VERSION < 3
+  if (m && m->nb_int) {
+    name = "int";
+    res = PyNumber_Int(x);
+  }
+  else if (m && m->nb_long) {
+    name = "long";
+    res = PyNumber_Long(x);
+  }
+#else
+  if (m && m->nb_int) {
+    name = "int";
+    res = PyNumber_Long(x);
+  }
+#endif
+  if (res) {
+#if PY_MAJOR_VERSION < 3
+    if (!PyInt_Check(res) && !PyLong_Check(res)) {
+#else
+    if (!PyLong_Check(res)) {
+#endif
+      PyErr_Format(PyExc_TypeError,
+                   "__%.4s__ returned non-%.4s (type %.200s)",
+                   name, name, Py_TYPE(res)->tp_name);
+      Py_DECREF(res);
+      return NULL;
+    }
+  }
+  else if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_TypeError,
+                    "an integer is required");
+  }
+  return res;
+}
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+  #include "longintrepr.h"
+ #endif
+#endif
+static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
+  Py_ssize_t ival;
+  PyObject *x;
+#if PY_MAJOR_VERSION < 3
+  if (likely(PyInt_CheckExact(b)))
+      return PyInt_AS_LONG(b);
+#endif
+  if (likely(PyLong_CheckExact(b))) {
+    #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+     #if CYTHON_USE_PYLONG_INTERNALS
+       switch (Py_SIZE(b)) {
+       case -1: return -(sdigit)((PyLongObject*)b)->ob_digit[0];
+       case  0: return 0;
+       case  1: return ((PyLongObject*)b)->ob_digit[0];
+       }
+     #endif
+    #endif
+  #if PY_VERSION_HEX < 0x02060000
+    return PyInt_AsSsize_t(b);
+  #else
+    return PyLong_AsSsize_t(b);
+  #endif
+  }
+  x = PyNumber_Index(b);
+  if (!x) return -1;
+  ival = PyInt_AsSsize_t(x);
+  Py_DECREF(x);
+  return ival;
+}
+static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
+#if PY_VERSION_HEX < 0x02050000
+   if (ival <= LONG_MAX)
+       return PyInt_FromLong((long)ival);
+   else {
+       unsigned char *bytes = (unsigned char *) &ival;
+       int one = 1; int little = (int)*(unsigned char*)&one;
+       return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0);
+   }
+#else
+   return PyInt_FromSize_t(ival);
+#endif
+}
+
+
+#endif /* Py_PYTHON_H */
diff --git a/pymusic/pybuffer.pxd b/pymusic/pybuffer.pxd
new file mode 100644
index 0000000..f789c25
--- /dev/null
+++ b/pymusic/pybuffer.pxd
@@ -0,0 +1,43 @@
+cimport mpi4py.MPI as MPI
+from mpi4py.mpi_c cimport *
+
+cdef extern from "music/pymusic_c.h":
+    object PyUnicodeString_FromString(const char*)
+
+from cpython.ref cimport PyObject
+
+# Python 3 buffer interface (PEP 3118)
+cdef extern from "Python.h":
+    ctypedef struct Py_buffer:
+        void* buf
+        PyObject* obj        # owned reference 
+        Py_ssize_t len
+        Py_ssize_t itemsize  # This is Py_ssize_t so it can be
+                              # pointed to by strides in simple case.*/
+        bint readonly
+        int ndim
+        char* format
+        Py_ssize_t *shape
+        Py_ssize_t *strides
+        Py_ssize_t *suboffsets
+        Py_ssize_t smalltable[2]  # static store for shape and strides of
+                                  # mono-dimensional buffers.
+        void *internal
+
+    cdef enum:
+        PyBUF_SIMPLE
+        PyBUF_WRITABLE
+        PyBUF_FORMAT
+        PyBUF_ANY_CONTIGUOUS
+        PyBUF_ND
+        PyBUF_STRIDES
+
+    int  PyObject_CheckBuffer(object)
+    int  PyObject_GetBuffer(object, Py_buffer *, int) except -1
+    void PyBuffer_Release(Py_buffer *)
+    int  PyBuffer_FillInfo(Py_buffer*, object, void*, Py_ssize_t, bint, int) except -1
+
+cdef class Buffer(object):
+    cdef Py_buffer pybuf
+    cdef MPI.Datatype dtype
+    cdef Py_ssize_t items
diff --git a/pymusic/pybuffer.pyx b/pymusic/pybuffer.pyx
new file mode 100644
index 0000000..98489ae
--- /dev/null
+++ b/pymusic/pybuffer.pyx
@@ -0,0 +1,66 @@
+#
+# distutils: language = c++
+#
+
+# Compatible with Python >= 2.6, Cython
+# Not PYPY apparently
+
+from libc.stdlib cimport malloc, free
+
+from mpi4py import MPI
+
+###########################################################
+
+cdef dict TypeDict = {
+    "?" : MPI.C_BOOL,
+    "c" : MPI.CHAR,
+    "b" : MPI.SIGNED_CHAR,
+    "h" : MPI.SHORT,
+    "i" : MPI.INT,
+    "l" : MPI.LONG,
+    "q" : MPI.LONG_LONG,
+    "p" : MPI.AINT,
+    "B" : MPI.UNSIGNED_CHAR,
+    "H" : MPI.UNSIGNED_SHORT,
+    "I" : MPI.UNSIGNED,
+    "L" : MPI.UNSIGNED_LONG,
+    "Q" : MPI.UNSIGNED_LONG_LONG,
+    "f" : MPI.FLOAT,
+    "d" : MPI.DOUBLE,
+    "g" : MPI.LONG_DOUBLE,
+    "Zf": MPI.C_FLOAT_COMPLEX,
+    "Zd": MPI.C_DOUBLE_COMPLEX,
+    "Zg": MPI.C_LONG_DOUBLE_COMPLEX,
+    "F" : MPI.C_FLOAT_COMPLEX,
+    "D" : MPI.C_DOUBLE_COMPLEX,
+    "G" : MPI.C_LONG_DOUBLE_COMPLEX,
+}
+
+cdef object getformat(Py_buffer* pybuf):
+    cdef object obj = <object> pybuf.obj
+
+    # numpy.ndarray
+    try: return obj.dtype.char
+    except (AttributeError, TypeError): pass
+
+    # array.array
+    try: return obj.typecode
+    except (AttributeError, TypeError): pass
+
+    if pybuf.format is NULL: return "B"
+    return PyUnicodeString_FromString(pybuf.format)
+
+cdef int bufflags = PyBUF_ANY_CONTIGUOUS | PyBUF_WRITABLE | PyBUF_FORMAT
+
+cdef class Buffer(object):
+    def __cinit__(self, object data):
+        if not PyObject_CheckBuffer(data):
+            raise TypeError("object does not present buffer interface")
+
+        cdef Py_buffer* pybuf = &self.pybuf
+        PyObject_GetBuffer(data, pybuf, bufflags)
+        self.dtype = TypeDict[getformat(pybuf)]
+        self.items = pybuf.len / pybuf.itemsize
+
+    def __dealloc__(self):
+        PyBuffer_Release(&self.pybuf)
diff --git a/pymusic/pymusic.cpp b/pymusic/pymusic.cpp
new file mode 100644
index 0000000..ea0b6ff
--- /dev/null
+++ b/pymusic/pymusic.cpp
@@ -0,0 +1,15159 @@
+/* Generated by Cython 0.21.1 */
+
+#define PY_SSIZE_T_CLEAN
+#ifndef CYTHON_USE_PYLONG_INTERNALS
+#ifdef PYLONG_BITS_IN_DIGIT
+#define CYTHON_USE_PYLONG_INTERNALS 0
+#else
+#include "pyconfig.h"
+#ifdef PYLONG_BITS_IN_DIGIT
+#define CYTHON_USE_PYLONG_INTERNALS 1
+#else
+#define CYTHON_USE_PYLONG_INTERNALS 0
+#endif
+#endif
+#endif
+#include "Python.h"
+#ifndef Py_PYTHON_H
+    #error Python headers needed to compile C extensions, please install development version of Python.
+#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03020000)
+    #error Cython requires Python 2.6+ or Python 3.2+.
+#else
+#define CYTHON_ABI "0_21_1"
+#include <stddef.h>
+#ifndef offsetof
+#define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
+#endif
+#if !defined(WIN32) && !defined(MS_WINDOWS)
+  #ifndef __stdcall
+    #define __stdcall
+  #endif
+  #ifndef __cdecl
+    #define __cdecl
+  #endif
+  #ifndef __fastcall
+    #define __fastcall
+  #endif
+#endif
+#ifndef DL_IMPORT
+  #define DL_IMPORT(t) t
+#endif
+#ifndef DL_EXPORT
+  #define DL_EXPORT(t) t
+#endif
+#ifndef PY_LONG_LONG
+  #define PY_LONG_LONG LONG_LONG
+#endif
+#ifndef Py_HUGE_VAL
+  #define Py_HUGE_VAL HUGE_VAL
+#endif
+#ifdef PYPY_VERSION
+#define CYTHON_COMPILING_IN_PYPY 1
+#define CYTHON_COMPILING_IN_CPYTHON 0
+#else
+#define CYTHON_COMPILING_IN_PYPY 0
+#define CYTHON_COMPILING_IN_CPYTHON 1
+#endif
+#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600
+#define Py_OptimizeFlag 0
+#endif
+#define __PYX_BUILD_PY_SSIZE_T "n"
+#define CYTHON_FORMAT_SSIZE_T "z"
+#if PY_MAJOR_VERSION < 3
+  #define __Pyx_BUILTIN_MODULE_NAME "__builtin__"
+  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
+          PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
+  #define __Pyx_DefaultClassType PyClass_Type
+#else
+  #define __Pyx_BUILTIN_MODULE_NAME "builtins"
+  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \
+          PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
+  #define __Pyx_DefaultClassType PyType_Type
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define Py_TPFLAGS_CHECKTYPES 0
+  #define Py_TPFLAGS_HAVE_INDEX 0
+  #define Py_TPFLAGS_HAVE_NEWBUFFER 0
+#endif
+#if PY_VERSION_HEX < 0x030400a1 && !defined(Py_TPFLAGS_HAVE_FINALIZE)
+  #define Py_TPFLAGS_HAVE_FINALIZE 0
+#endif
+#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND)
+  #define CYTHON_PEP393_ENABLED 1
+  #define __Pyx_PyUnicode_READY(op)       (likely(PyUnicode_IS_READY(op)) ? \
+                                              0 : _PyUnicode_Ready((PyObject *)(op)))
+  #define __Pyx_PyUnicode_GET_LENGTH(u)   PyUnicode_GET_LENGTH(u)
+  #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
+  #define __Pyx_PyUnicode_KIND(u)         PyUnicode_KIND(u)
+  #define __Pyx_PyUnicode_DATA(u)         PyUnicode_DATA(u)
+  #define __Pyx_PyUnicode_READ(k, d, i)   PyUnicode_READ(k, d, i)
+#else
+  #define CYTHON_PEP393_ENABLED 0
+  #define __Pyx_PyUnicode_READY(op)       (0)
+  #define __Pyx_PyUnicode_GET_LENGTH(u)   PyUnicode_GET_SIZE(u)
+  #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
+  #define __Pyx_PyUnicode_KIND(u)         (sizeof(Py_UNICODE))
+  #define __Pyx_PyUnicode_DATA(u)         ((void*)PyUnicode_AS_UNICODE(u))
+  #define __Pyx_PyUnicode_READ(k, d, i)   ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i]))
+#endif
+#if CYTHON_COMPILING_IN_PYPY
+  #define __Pyx_PyUnicode_Concat(a, b)      PyNumber_Add(a, b)
+  #define __Pyx_PyUnicode_ConcatSafe(a, b)  PyNumber_Add(a, b)
+  #define __Pyx_PyFrozenSet_Size(s)         PyObject_Size(s)
+#else
+  #define __Pyx_PyUnicode_Concat(a, b)      PyUnicode_Concat(a, b)
+  #define __Pyx_PyUnicode_ConcatSafe(a, b)  ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ? \
+      PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b))
+  #define __Pyx_PyFrozenSet_Size(s)         PySet_Size(s)
+#endif
+#define __Pyx_PyString_FormatSafe(a, b)   ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b))
+#define __Pyx_PyUnicode_FormatSafe(a, b)  ((unlikely((a) == Py_None)) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyString_Format(a, b)  PyUnicode_Format(a, b)
+#else
+  #define __Pyx_PyString_Format(a, b)  PyString_Format(a, b)
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define PyBaseString_Type            PyUnicode_Type
+  #define PyStringObject               PyUnicodeObject
+  #define PyString_Type                PyUnicode_Type
+  #define PyString_Check               PyUnicode_Check
+  #define PyString_CheckExact          PyUnicode_CheckExact
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj)
+  #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj)
+#else
+  #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj))
+  #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj))
+#endif
+#ifndef PySet_CheckExact
+  #define PySet_CheckExact(obj)        (Py_TYPE(obj) == &PySet_Type)
+#endif
+#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
+#if PY_MAJOR_VERSION >= 3
+  #define PyIntObject                  PyLongObject
+  #define PyInt_Type                   PyLong_Type
+  #define PyInt_Check(op)              PyLong_Check(op)
+  #define PyInt_CheckExact(op)         PyLong_CheckExact(op)
+  #define PyInt_FromString             PyLong_FromString
+  #define PyInt_FromUnicode            PyLong_FromUnicode
+  #define PyInt_FromLong               PyLong_FromLong
+  #define PyInt_FromSize_t             PyLong_FromSize_t
+  #define PyInt_FromSsize_t            PyLong_FromSsize_t
+  #define PyInt_AsLong                 PyLong_AsLong
+  #define PyInt_AS_LONG                PyLong_AS_LONG
+  #define PyInt_AsSsize_t              PyLong_AsSsize_t
+  #define PyInt_AsUnsignedLongMask     PyLong_AsUnsignedLongMask
+  #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
+  #define PyNumber_Int                 PyNumber_Long
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define PyBoolObject                 PyLongObject
+#endif
+#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY
+  #ifndef PyUnicode_InternFromString
+    #define PyUnicode_InternFromString(s) PyUnicode_FromString(s)
+  #endif
+#endif
+#if PY_VERSION_HEX < 0x030200A4
+  typedef long Py_hash_t;
+  #define __Pyx_PyInt_FromHash_t PyInt_FromLong
+  #define __Pyx_PyInt_AsHash_t   PyInt_AsLong
+#else
+  #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t
+  #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
+#endif
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func))
+#else
+  #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass)
+#endif
+#ifndef CYTHON_INLINE
+  #if defined(__GNUC__)
+    #define CYTHON_INLINE __inline__
+  #elif defined(_MSC_VER)
+    #define CYTHON_INLINE __inline
+  #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+    #define CYTHON_INLINE inline
+  #else
+    #define CYTHON_INLINE
+  #endif
+#endif
+#ifndef CYTHON_RESTRICT
+  #if defined(__GNUC__)
+    #define CYTHON_RESTRICT __restrict__
+  #elif defined(_MSC_VER) && _MSC_VER >= 1400
+    #define CYTHON_RESTRICT __restrict
+  #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+    #define CYTHON_RESTRICT restrict
+  #else
+    #define CYTHON_RESTRICT
+  #endif
+#endif
+#ifdef NAN
+#define __PYX_NAN() ((float) NAN)
+#else
+static CYTHON_INLINE float __PYX_NAN() {
+  /* Initialize NaN. The sign is irrelevant, an exponent with all bits 1 and
+   a nonzero mantissa means NaN. If the first bit in the mantissa is 1, it is
+   a quiet NaN. */
+  float value;
+  memset(&value, 0xFF, sizeof(value));
+  return value;
+}
+#endif
+#ifdef __cplusplus
+template<typename T>
+void __Pyx_call_destructor(T* x) {
+    x->~T();
+}
+#endif
+
+
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
+#else
+  #define __Pyx_PyNumber_Divide(x,y)         PyNumber_Divide(x,y)
+  #define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceDivide(x,y)
+#endif
+
+#ifndef __PYX_EXTERN_C
+  #ifdef __cplusplus
+    #define __PYX_EXTERN_C extern "C"
+  #else
+    #define __PYX_EXTERN_C extern
+  #endif
+#endif
+
+#if defined(WIN32) || defined(MS_WINDOWS)
+#define _USE_MATH_DEFINES
+#endif
+#include <math.h>
+#define __PYX_HAVE__pymusic
+#define __PYX_HAVE_API__pymusic
+#include "mpi.h"
+#include "string.h"
+#include <string>
+#include "ios"
+#include "new"
+#include "stdexcept"
+#include "typeinfo"
+#include "music/predict_rank.hh"
+#include "music/message.hh"
+#include "music/music_c.h"
+#include "music/event.hh"
+#include "music/data_map.hh"
+#include "music/index_map.hh"
+#include "music/permutation_index.hh"
+#include "music/linear_index.hh"
+#include "music/array_data.hh"
+#include "music/port.hh"
+#include "music/setup.hh"
+#include "music/runtime.hh"
+#include "music/pymusic_c.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "pythread.h"
+#ifdef _OPENMP
+#include <omp.h>
+#endif /* _OPENMP */
+
+#ifdef PYREX_WITHOUT_ASSERTIONS
+#define CYTHON_WITHOUT_ASSERTIONS
+#endif
+
+#ifndef CYTHON_UNUSED
+# if defined(__GNUC__)
+#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#     define CYTHON_UNUSED __attribute__ ((__unused__))
+#   else
+#     define CYTHON_UNUSED
+#   endif
+# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
+#   define CYTHON_UNUSED __attribute__ ((__unused__))
+# else
+#   define CYTHON_UNUSED
+# endif
+#endif
+typedef struct {PyObject **p; char *s; const Py_ssize_t n; const char* encoding;
+                const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry;
+
+#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
+#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 1
+#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
+#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
+#define __Pyx_fits_Py_ssize_t(v, type, is_signed)  (    \
+    (sizeof(type) < sizeof(Py_ssize_t))  ||             \
+    (sizeof(type) > sizeof(Py_ssize_t) &&               \
+          likely(v < (type)PY_SSIZE_T_MAX ||            \
+                 v == (type)PY_SSIZE_T_MAX)  &&         \
+          (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||       \
+                                v == (type)PY_SSIZE_T_MIN)))  ||  \
+    (sizeof(type) == sizeof(Py_ssize_t) &&              \
+          (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||        \
+                               v == (type)PY_SSIZE_T_MAX)))  )
+static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject*);
+static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length);
+#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s))
+#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l)
+#define __Pyx_PyBytes_FromString        PyBytes_FromString
+#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*);
+#if PY_MAJOR_VERSION < 3
+    #define __Pyx_PyStr_FromString        __Pyx_PyBytes_FromString
+    #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
+#else
+    #define __Pyx_PyStr_FromString        __Pyx_PyUnicode_FromString
+    #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize
+#endif
+#define __Pyx_PyObject_AsSString(s)    ((signed char*) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_AsUString(s)    ((unsigned char*) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_FromUString(s)  __Pyx_PyObject_FromString((const char*)s)
+#define __Pyx_PyBytes_FromUString(s)   __Pyx_PyBytes_FromString((const char*)s)
+#define __Pyx_PyByteArray_FromUString(s)   __Pyx_PyByteArray_FromString((const char*)s)
+#define __Pyx_PyStr_FromUString(s)     __Pyx_PyStr_FromString((const char*)s)
+#define __Pyx_PyUnicode_FromUString(s) __Pyx_PyUnicode_FromString((const char*)s)
+#if PY_MAJOR_VERSION < 3
+static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
+{
+    const Py_UNICODE *u_end = u;
+    while (*u_end++) ;
+    return (size_t)(u_end - u - 1);
+}
+#else
+#define __Pyx_Py_UNICODE_strlen Py_UNICODE_strlen
+#endif
+#define __Pyx_PyUnicode_FromUnicode(u)       PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u))
+#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode
+#define __Pyx_PyUnicode_AsUnicode            PyUnicode_AsUnicode
+#define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None)
+#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
+static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
+static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
+static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
+static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
+#else
+#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x)
+#endif
+#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
+#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+static int __Pyx_sys_getdefaultencoding_not_ascii;
+static int __Pyx_init_sys_getdefaultencoding_params(void) {
+    PyObject* sys;
+    PyObject* default_encoding = NULL;
+    PyObject* ascii_chars_u = NULL;
+    PyObject* ascii_chars_b = NULL;
+    const char* default_encoding_c;
+    sys = PyImport_ImportModule("sys");
+    if (!sys) goto bad;
+    default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL);
+    Py_DECREF(sys);
+    if (!default_encoding) goto bad;
+    default_encoding_c = PyBytes_AsString(default_encoding);
+    if (!default_encoding_c) goto bad;
+    if (strcmp(default_encoding_c, "ascii") == 0) {
+        __Pyx_sys_getdefaultencoding_not_ascii = 0;
+    } else {
+        char ascii_chars[128];
+        int c;
+        for (c = 0; c < 128; c++) {
+            ascii_chars[c] = c;
+        }
+        __Pyx_sys_getdefaultencoding_not_ascii = 1;
+        ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL);
+        if (!ascii_chars_u) goto bad;
+        ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL);
+        if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) {
+            PyErr_Format(
+                PyExc_ValueError,
+                "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.",
+                default_encoding_c);
+            goto bad;
+        }
+        Py_DECREF(ascii_chars_u);
+        Py_DECREF(ascii_chars_b);
+    }
+    Py_DECREF(default_encoding);
+    return 0;
+bad:
+    Py_XDECREF(default_encoding);
+    Py_XDECREF(ascii_chars_u);
+    Py_XDECREF(ascii_chars_b);
+    return -1;
+}
+#endif
+#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3
+#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL)
+#else
+#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL)
+#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
+static char* __PYX_DEFAULT_STRING_ENCODING;
+static int __Pyx_init_sys_getdefaultencoding_params(void) {
+    PyObject* sys;
+    PyObject* default_encoding = NULL;
+    char* default_encoding_c;
+    sys = PyImport_ImportModule("sys");
+    if (!sys) goto bad;
+    default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL);
+    Py_DECREF(sys);
+    if (!default_encoding) goto bad;
+    default_encoding_c = PyBytes_AsString(default_encoding);
+    if (!default_encoding_c) goto bad;
+    __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c));
+    if (!__PYX_DEFAULT_STRING_ENCODING) goto bad;
+    strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c);
+    Py_DECREF(default_encoding);
+    return 0;
+bad:
+    Py_XDECREF(default_encoding);
+    return -1;
+}
+#endif
+#endif
+
+
+/* Test for GCC > 2.95 */
+#if defined(__GNUC__)     && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))
+  #define likely(x)   __builtin_expect(!!(x), 1)
+  #define unlikely(x) __builtin_expect(!!(x), 0)
+#else /* !__GNUC__ or GCC < 2.95 */
+  #define likely(x)   (x)
+  #define unlikely(x) (x)
+#endif /* __GNUC__ */
+
+static PyObject *__pyx_m;
+static PyObject *__pyx_d;
+static PyObject *__pyx_b;
+static PyObject *__pyx_empty_tuple;
+static PyObject *__pyx_empty_bytes;
+static int __pyx_lineno;
+static int __pyx_clineno = 0;
+static const char * __pyx_cfilenm= __FILE__;
+static const char *__pyx_filename;
+
+
+static const char *__pyx_f[] = {
+  "pymusic.pyx",
+  "array.pxd",
+  "stringsource",
+  "stringsource",
+  "MPI.pxd",
+  "music/pybuffer.pxd",
+  "type.pxd",
+  "bool.pxd",
+  "complex.pxd",
+};
+
+/*--- Type declarations ---*/
+#ifndef _ARRAYARRAY_H
+struct arrayobject;
+typedef struct arrayobject arrayobject;
+#endif
+struct PyMPIStatusObject;
+struct PyMPIDatatypeObject;
+struct PyMPIRequestObject;
+struct PyMPIPrequestObject;
+struct PyMPIGrequestObject;
+struct PyMPIOpObject;
+struct PyMPIGroupObject;
+struct PyMPIInfoObject;
+struct PyMPIErrhandlerObject;
+struct PyMPICommObject;
+struct PyMPIIntracommObject;
+struct PyMPICartcommObject;
+struct PyMPIGraphcommObject;
+struct PyMPIDistgraphcommObject;
+struct PyMPIIntercommObject;
+struct PyMPIWinObject;
+struct PyMPIFileObject;
+struct __pyx_obj_5music_8pybuffer_Buffer;
+struct __pyx_obj_7pymusic_Setup;
+struct __pyx_obj_7pymusic_Runtime;
+struct __pyx_obj_7pymusic_Port;
+struct __pyx_obj_7pymusic_ContInputPort;
+struct __pyx_obj_7pymusic_ContOutputPort;
+struct __pyx_obj_7pymusic_EventInputPort;
+struct __pyx_obj_7pymusic_EventOutputPort;
+struct __pyx_obj_7pymusic_MessageInputPort;
+struct __pyx_obj_7pymusic_MessageOutputPort;
+struct __pyx_obj_7pymusic_DataMap;
+struct __pyx_obj_7pymusic_IndexMap;
+struct __pyx_obj_7pymusic_EventHandler;
+struct __pyx_obj_7pymusic_MessageHandler;
+struct __pyx_obj_7pymusic__Index;
+struct __pyx_obj_7pymusic___pyx_scope_struct____iter__;
+struct __pyx_t_7pymusic_Args;
+typedef struct __pyx_t_7pymusic_Args __pyx_t_7pymusic_Args;
+
+/* "pymusic.pyx":48
+ * # argv = [exec, op[1], ..., op[argc-1], NULL]
+ * # """
+ * ctypedef struct Args:             # <<<<<<<<<<<<<<
+ *     int argc
+ *     char** argv
+ */
+struct __pyx_t_7pymusic_Args {
+  int argc;
+  char **argv;
+};
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":49
+ *     ctypedef MPI_Offset Offset "MPI_Offset"
+ * 
+ * ctypedef public api class Status [             # <<<<<<<<<<<<<<
+ *     type   PyMPIStatus_Type,
+ *     object PyMPIStatusObject,
+ */
+struct PyMPIStatusObject {
+  PyObject_HEAD
+  MPI_Status ob_mpi;
+  int flags;
+};
+typedef struct PyMPIStatusObject PyMPIStatusObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIStatus_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":56
+ *     cdef int        flags
+ * 
+ * ctypedef public api class Datatype [             # <<<<<<<<<<<<<<
+ *     type   PyMPIDatatype_Type,
+ *     object PyMPIDatatypeObject,
+ */
+struct PyMPIDatatypeObject {
+  PyObject_HEAD
+  MPI_Datatype ob_mpi;
+  int flags;
+};
+typedef struct PyMPIDatatypeObject PyMPIDatatypeObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIDatatype_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":63
+ *     cdef int          flags
+ * 
+ * ctypedef public api class Request [             # <<<<<<<<<<<<<<
+ *     type   PyMPIRequest_Type,
+ *     object PyMPIRequestObject,
+ */
+struct PyMPIRequestObject {
+  PyObject_HEAD
+  MPI_Request ob_mpi;
+  int flags;
+  PyObject *ob_buf;
+};
+typedef struct PyMPIRequestObject PyMPIRequestObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIRequest_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":71
+ *     cdef object      ob_buf
+ * 
+ * ctypedef public api class Prequest(Request) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIPrequest_Type,
+ *     object PyMPIPrequestObject,
+ */
+struct PyMPIPrequestObject {
+  struct PyMPIRequestObject __pyx_base;
+};
+typedef struct PyMPIPrequestObject PyMPIPrequestObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIPrequest_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":77
+ *     pass
+ * 
+ * ctypedef public api class Grequest(Request) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIGrequest_Type,
+ *     object PyMPIGrequestObject,
+ */
+struct PyMPIGrequestObject {
+  struct PyMPIRequestObject __pyx_base;
+  MPI_Request ob_grequest;
+};
+typedef struct PyMPIGrequestObject PyMPIGrequestObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIGrequest_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":83
+ *     cdef MPI_Request ob_grequest
+ * 
+ * ctypedef public api class Op [             # <<<<<<<<<<<<<<
+ *     type   PyMPIOp_Type,
+ *     object PyMPIOpObject,
+ */
+struct PyMPIOpObject {
+  PyObject_HEAD
+  MPI_Op ob_mpi;
+  int flags;
+  PyObject *(*ob_func)(PyObject *, PyObject *);
+  int ob_usrid;
+};
+typedef struct PyMPIOpObject PyMPIOpObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIOp_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":92
+ *     cdef int    ob_usrid
+ * 
+ * ctypedef public api class Group [             # <<<<<<<<<<<<<<
+ *     type   PyMPIGroup_Type,
+ *     object PyMPIGroupObject,
+ */
+struct PyMPIGroupObject {
+  PyObject_HEAD
+  MPI_Group ob_mpi;
+  int flags;
+};
+typedef struct PyMPIGroupObject PyMPIGroupObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIGroup_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":99
+ *     cdef int       flags
+ * 
+ * ctypedef public api class Info [             # <<<<<<<<<<<<<<
+ *     type   PyMPIInfo_Type,
+ *     object PyMPIInfoObject,
+ */
+struct PyMPIInfoObject {
+  PyObject_HEAD
+  MPI_Info ob_mpi;
+  int flags;
+};
+typedef struct PyMPIInfoObject PyMPIInfoObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIInfo_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":106
+ *     cdef int      flags
+ * 
+ * ctypedef public api class Errhandler [             # <<<<<<<<<<<<<<
+ *     type   PyMPIErrhandler_Type,
+ *     object PyMPIErrhandlerObject,
+ */
+struct PyMPIErrhandlerObject {
+  PyObject_HEAD
+  MPI_Errhandler ob_mpi;
+  int flags;
+};
+typedef struct PyMPIErrhandlerObject PyMPIErrhandlerObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIErrhandler_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":113
+ *     cdef int            flags
+ * 
+ * ctypedef public api class Comm [             # <<<<<<<<<<<<<<
+ *     type   PyMPIComm_Type,
+ *     object PyMPICommObject,
+ */
+struct PyMPICommObject {
+  PyObject_HEAD
+  MPI_Comm ob_mpi;
+  int flags;
+};
+typedef struct PyMPICommObject PyMPICommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIComm_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":120
+ *     cdef int      flags
+ * 
+ * ctypedef public api class Intracomm(Comm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIIntracomm_Type,
+ *     object PyMPIIntracommObject,
+ */
+struct PyMPIIntracommObject {
+  struct PyMPICommObject __pyx_base;
+};
+typedef struct PyMPIIntracommObject PyMPIIntracommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIIntracomm_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":126
+ *     pass
+ * 
+ * ctypedef public api class Cartcomm(Intracomm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPICartcomm_Type,
+ *     object PyMPICartcommObject,
+ */
+struct PyMPICartcommObject {
+  struct PyMPIIntracommObject __pyx_base;
+};
+typedef struct PyMPICartcommObject PyMPICartcommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPICartcomm_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":132
+ *     pass
+ * 
+ * ctypedef public api class Graphcomm(Intracomm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIGraphcomm_Type,
+ *     object PyMPIGraphcommObject,
+ */
+struct PyMPIGraphcommObject {
+  struct PyMPIIntracommObject __pyx_base;
+};
+typedef struct PyMPIGraphcommObject PyMPIGraphcommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIGraphcomm_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":138
+ *     pass
+ * 
+ * ctypedef public api class Distgraphcomm(Intracomm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIDistgraphcomm_Type,
+ *     object PyMPIDistgraphcommObject,
+ */
+struct PyMPIDistgraphcommObject {
+  struct PyMPIIntracommObject __pyx_base;
+};
+typedef struct PyMPIDistgraphcommObject PyMPIDistgraphcommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIDistgraphcomm_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":144
+ *     pass
+ * 
+ * ctypedef public api class Intercomm(Comm) [             # <<<<<<<<<<<<<<
+ *     type   PyMPIIntercomm_Type,
+ *     object PyMPIIntercommObject,
+ */
+struct PyMPIIntercommObject {
+  struct PyMPICommObject __pyx_base;
+};
+typedef struct PyMPIIntercommObject PyMPIIntercommObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIIntercomm_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":150
+ *     pass
+ * 
+ * ctypedef public api class Win [             # <<<<<<<<<<<<<<
+ *     type   PyMPIWin_Type,
+ *     object PyMPIWinObject,
+ */
+struct PyMPIWinObject {
+  PyObject_HEAD
+  MPI_Win ob_mpi;
+  int flags;
+};
+typedef struct PyMPIWinObject PyMPIWinObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIWin_Type;
+
+/* "../../../../../usr/lib64/python2.7/site-packages/openmpi/mpi4py/include/mpi4py/MPI.pxd":157
+ *     cdef int     flags
+ * 
+ * ctypedef public api class File [             # <<<<<<<<<<<<<<
+ *     type   PyMPIFile_Type,
+ *     object PyMPIFileObject,
+ */
+struct PyMPIFileObject {
+  PyObject_HEAD
+  MPI_File ob_mpi;
+  int flags;
+};
+typedef struct PyMPIFileObject PyMPIFileObject;
+
+__PYX_EXTERN_C DL_EXPORT(PyTypeObject) PyMPIFile_Type;
+
+/* "music/pybuffer.pxd":40
+ *     int  PyBuffer_FillInfo(Py_buffer*, object, void*, Py_ssize_t, bint, int) except -1
+ * 
+ * cdef class Buffer(object):             # <<<<<<<<<<<<<<
+ *     cdef Py_buffer pybuf
+ *     cdef MPI.Datatype dtype
+ */
+struct __pyx_obj_5music_8pybuffer_Buffer {
+  PyObject_HEAD
+  Py_buffer pybuf;
+  struct PyMPIDatatypeObject *dtype;
+  Py_ssize_t items;
+};
+
+
+/* "pymusic.pxd":164
+ * ###########################################################
+ * 
+ * cdef class Setup(object):             # <<<<<<<<<<<<<<
+ *     cdef CSetup* ptr
+ *     cdef list argv
+ */
+struct __pyx_obj_7pymusic_Setup {
+  PyObject_HEAD
+  struct __pyx_vtabstruct_7pymusic_Setup *__pyx_vtab;
+  MUSIC::Setup *ptr;
+  PyObject *argv;
+  int provided;
+  struct PyMPIIntracommObject *comm;
+  PyObject *ports;
+};
+
+
+/* "pymusic.pxd":176
+ * ###########################################################
+ * 
+ * cdef class Runtime(object):             # <<<<<<<<<<<<<<
+ *     cdef CRuntime* ptr
+ *     cdef readonly MPI.Intracomm comm
+ */
+struct __pyx_obj_7pymusic_Runtime {
+  PyObject_HEAD
+  MUSIC::Runtime *ptr;
+  struct PyMPIIntracommObject *comm;
+  PyObject *ports;
+};
+
+
+/* "pymusic.pxd":183
+ * ###########################################################
+ * 
+ * cdef class Port(object):             # <<<<<<<<<<<<<<
+ *     cdef CPort* ptr
+ *     cpdef object null(self)
+ */
+struct __pyx_obj_7pymusic_Port {
+  PyObject_HEAD
+  struct __pyx_vtabstruct_7pymusic_Port *__pyx_vtab;
+  MUSIC::Port *ptr;
+};
+
+
+/* "pymusic.pxd":190
+ * ## a capital crime ^^^^
+ * 
+ * cdef class ContInputPort(Port):             # <<<<<<<<<<<<<<
+ *     pass
+ * 
+ */
+struct __pyx_obj_7pymusic_ContInputPort {
+  struct __pyx_obj_7pymusic_Port __pyx_base;
+};
+
+
+/* "pymusic.pxd":193
+ *     pass
+ * 
+ * cdef class ContOutputPort(Port):             # <<<<<<<<<<<<<<
+ *     pass
+ * 
+ */
+struct __pyx_obj_7pymusic_ContOutputPort {
+  struct __pyx_obj_7pymusic_Port __pyx_base;
+};
+
+
+/* "pymusic.pxd":196
+ *     pass
+ * 
+ * cdef class EventInputPort(Port):             # <<<<<<<<<<<<<<
+ *     cdef set events
+ *     cpdef object null(self)
+ */
+struct __pyx_obj_7pymusic_EventInputPort {
+  struct __pyx_obj_7pymusic_Port __pyx_base;
+  PyObject *events;
+};
+
+
+/* "pymusic.pxd":200
+ *     cpdef object null(self)
+ * 
+ * cdef class EventOutputPort(Port):             # <<<<<<<<<<<<<<
+ *     pass
+ * 
+ */
+struct __pyx_obj_7pymusic_EventOutputPort {
+  struct __pyx_obj_7pymusic_Port __pyx_base;
+};
+
+
+/* "pymusic.pxd":203
+ *     pass
+ * 
+ * cdef class MessageInputPort(Port):             # <<<<<<<<<<<<<<
+ *     cdef set events
+ *     cpdef object null(self)
+ */
+struct __pyx_obj_7pymusic_MessageInputPort {
+  struct __pyx_obj_7pymusic_Port __pyx_base;
+  PyObject *events;
+};
+
+
+/* "pymusic.pxd":207
+ *     cpdef object null(self)
+ * 
+ * cdef class MessageOutputPort(Port):             # <<<<<<<<<<<<<<
+ *     cdef bint pickled
+ * 
+ */
+struct __pyx_obj_7pymusic_MessageOutputPort {
+  struct __pyx_obj_7pymusic_Port __pyx_base;
+  int pickled;
+};
+
+
+/* "pymusic.pxd":214
+ * from music.pybuffer cimport Buffer
+ * 
+ * cdef class DataMap(object):             # <<<<<<<<<<<<<<
+ *     cdef CDataMap* ptr
+ *     cdef Buffer buf
+ */
+struct __pyx_obj_7pymusic_DataMap {
+  PyObject_HEAD
+  MUSIC::DataMap *ptr;
+  struct __pyx_obj_5music_8pybuffer_Buffer *buf;
+};
+
+
+/* "pymusic.pxd":218
+ *     cdef Buffer buf
+ * 
+ * cdef class IndexMap(object):             # <<<<<<<<<<<<<<
+ *     cdef CIndexMap* ptr
+ *     cdef Buffer buf
+ */
+struct __pyx_obj_7pymusic_IndexMap {
+  PyObject_HEAD
+  MUSIC::IndexMap *ptr;
+  struct __pyx_obj_5music_8pybuffer_Buffer *buf;
+};
+
+
+/* "pymusic.pxd":222
+ *     cdef Buffer buf
+ * 
+ * cdef class EventHandler:             # <<<<<<<<<<<<<<
+ *     cdef CEventHandler* ptr
+ *     cdef object func
+ */
+struct __pyx_obj_7pymusic_EventHandler {
+  PyObject_HEAD
+  MUSIC::EventHandler *ptr;
+  PyObject *func;
+};
+
+
+/* "pymusic.pxd":226
+ *     cdef object func
+ * 
+ * cdef class MessageHandler:             # <<<<<<<<<<<<<<
+ *     cdef CMessageHandler* ptr
+ *     cdef object func
+ */
+struct __pyx_obj_7pymusic_MessageHandler {
+  PyObject_HEAD
+  MUSIC::MessageHandler *ptr;
+  PyObject *func;
+};
+
+
+/* "pymusic.pyx":636
+ *     def __dealloc__(self): del self.ptr
+ * 
+ * cdef class _Index:             # <<<<<<<<<<<<<<
+ *     """
+ *     Internal: the type of the variable Index
+ */
+struct __pyx_obj_7pymusic__Index {
+  PyObject_HEAD
+  int GLOBAL;
+  int LOCAL;
+  PyObject *backmap;
+};
+
+
+/* "pymusic.pyx":538
+ *     def tick(self): tick(self.ptr)
+ * 
+ *     def __iter__(self):             # <<<<<<<<<<<<<<
+ *         cdef CRuntime* ptr = self.ptr
+ *         while True:
+ */
+struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ {
+  PyObject_HEAD
+  MUSIC::Runtime *__pyx_v_ptr;
+  struct __pyx_obj_7pymusic_Runtime *__pyx_v_self;
+};
+
+
+
+/* "pymusic.pyx":348
+ * 
+ * import sys
+ * cdef class Setup(object):             # <<<<<<<<<<<<<<
+ *     """
+ *     API to setup the music interface.
+ */
+
+struct __pyx_vtabstruct_7pymusic_Setup {
+  PyObject *(*null)(struct __pyx_obj_7pymusic_Setup *);
+  struct PyMPIIntracommObject *(*getcomm)(struct __pyx_obj_7pymusic_Setup *, int __pyx_skip_dispatch);
+};
+static struct __pyx_vtabstruct_7pymusic_Setup *__pyx_vtabptr_7pymusic_Setup;
+
+
+/* "pymusic.pyx":90
+ * ###########################################################
+ * 
+ * cdef class Port(object):             # <<<<<<<<<<<<<<
+ *     """
+ *     Base Port class.
+ */
+
+struct __pyx_vtabstruct_7pymusic_Port {
+  PyObject *(*null)(struct __pyx_obj_7pymusic_Port *, int __pyx_skip_dispatch);
+};
+static struct __pyx_vtabstruct_7pymusic_Port *__pyx_vtabptr_7pymusic_Port;
+
+
+/* "pymusic.pyx":138
+ *         return self.ptr.width()
+ * 
+ * cdef class ContInputPort(Port):             # <<<<<<<<<<<<<<
+ *     """
+ *     ContInputPort maps data indices between sources and sinks. This is
+ */
+
+struct __pyx_vtabstruct_7pymusic_ContInputPort {
+  struct __pyx_vtabstruct_7pymusic_Port __pyx_base;
+};
+static struct __pyx_vtabstruct_7pymusic_ContInputPort *__pyx_vtabptr_7pymusic_ContInputPort;
+
+
+/* "pymusic.pyx":178
+ *         mapImpl(ptr, d.ptr, delay, maxBuffered, interpolate)
+ * 
+ * cdef class ContOutputPort(Port):             # <<<<<<<<<<<<<<
+ *     """
+ *     ContOutputPort maps data indices between sources and sinks. This
+ */
+
+struct __pyx_vtabstruct_7pymusic_ContOutputPort {
+  struct __pyx_vtabstruct_7pymusic_Port __pyx_base;
+};
+static struct __pyx_vtabstruct_7pymusic_ContOutputPort *__pyx_vtabptr_7pymusic_ContOutputPort;
+
+
+/* "pymusic.pyx":207
+ *         mapImpl(ptr, d.ptr, maxBuffered)
+ * 
+ * cdef class EventInputPort(Port):             # <<<<<<<<<<<<<<
+ *     """
+ *     Event sink. Maps 'events' to handlers. Events are spike-like
+ */
+
+struct __pyx_vtabstruct_7pymusic_EventInputPort {
+  struct __pyx_vtabstruct_7pymusic_Port __pyx_base;
+};
+static struct __pyx_vtabstruct_7pymusic_EventInputPort *__pyx_vtabptr_7pymusic_EventInputPort;
+
+
+/* "pymusic.pyx":252
+ *         self.events.add(eh)
+ * 
+ * cdef class EventOutputPort(Port):             # <<<<<<<<<<<<<<
+ *     """
+ *     Map events from this sink. See EventInputPort for description of
+ */
+
+struct __pyx_vtabstruct_7pymusic_EventOutputPort {
+  struct __pyx_vtabstruct_7pymusic_Port __pyx_base;
+};
+static struct __pyx_vtabstruct_7pymusic_EventOutputPort *__pyx_vtabptr_7pymusic_EventOutputPort;
+
+
+/* "pymusic.pyx":277
+ *         insertEventImpl(ptr, time, index)
+ * 
+ * cdef class MessageInputPort(Port):             # <<<<<<<<<<<<<<
+ *     """
+ *     Maps 'events' to handlers.
+ */
+
+struct __pyx_vtabstruct_7pymusic_MessageInputPort {
+  struct __pyx_vtabstruct_7pymusic_Port __pyx_base;
+};
+static struct __pyx_vtabstruct_7pymusic_MessageInputPort *__pyx_vtabptr_7pymusic_MessageInputPort;
+
+
+/* "pymusic.pyx":313
+ *         self.events.add(eh)
+ * 
+ * cdef class MessageOutputPort(Port):             # <<<<<<<<<<<<<<
+ *     """
+ *     The source of "messages". A message is a python object that is
+ */
+
+struct __pyx_vtabstruct_7pymusic_MessageOutputPort {
+  struct __pyx_vtabstruct_7pymusic_Port __pyx_base;
+};
+static struct __pyx_vtabstruct_7pymusic_MessageOutputPort *__pyx_vtabptr_7pymusic_MessageOutputPort;
+#ifndef CYTHON_REFNANNY
+  #define CYTHON_REFNANNY 0
+#endif
+#if CYTHON_REFNANNY
+  typedef struct {
+    void (*INCREF)(void*, PyObject*, int);
+    void (*DECREF)(void*, PyObject*, int);
+    void (*GOTREF)(void*, PyObject*, int);
+    void (*GIVEREF)(void*, PyObject*, int);
+    void* (*SetupContext)(const char*, int, const char*);
+    void (*FinishContext)(void**);
+  } __Pyx_RefNannyAPIStruct;
+  static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
+  static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname);
+  #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
+#ifdef WITH_THREAD
+  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
+          if (acquire_gil) { \
+              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure(); \
+              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+              PyGILState_Release(__pyx_gilstate_save); \
+          } else { \
+              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__); \
+          }
+#else
+  #define __Pyx_RefNannySetupContext(name, acquire_gil) \
+          __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
+#endif
+  #define __Pyx_RefNannyFinishContext() \
+          __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
+  #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_XINCREF(r)  do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0)
+  #define __Pyx_XDECREF(r)  do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0)
+  #define __Pyx_XGOTREF(r)  do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0)
+  #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
+#else
+  #define __Pyx_RefNannyDeclarations
+  #define __Pyx_RefNannySetupContext(name, acquire_gil)
+  #define __Pyx_RefNannyFinishContext()
+  #define __Pyx_INCREF(r) Py_INCREF(r)
+  #define __Pyx_DECREF(r) Py_DECREF(r)
+  #define __Pyx_GOTREF(r)
+  #define __Pyx_GIVEREF(r)
+  #define __Pyx_XINCREF(r) Py_XINCREF(r)
+  #define __Pyx_XDECREF(r) Py_XDECREF(r)
+  #define __Pyx_XGOTREF(r)
+  #define __Pyx_XGIVEREF(r)
+#endif
+#define __Pyx_XDECREF_SET(r, v) do {                            \
+        PyObject *tmp = (PyObject *) r;                         \
+        r = v; __Pyx_XDECREF(tmp);                              \
+    } while (0)
+#define __Pyx_DECREF_SET(r, v) do {                             \
+        PyObject *tmp = (PyObject *) r;                         \
+        r = v; __Pyx_DECREF(tmp);                               \
+    } while (0)
+#define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
+#define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) {
+    PyTypeObject* tp = Py_TYPE(obj);
+    if (likely(tp->tp_getattro))
+        return tp->tp_getattro(obj, attr_name);
+#if PY_MAJOR_VERSION < 3
+    if (likely(tp->tp_getattr))
+        return tp->tp_getattr(obj, PyString_AS_STRING(attr_name));
+#endif
+    return PyObject_GetAttr(obj, attr_name);
+}
+#else
+#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n)
+#endif
+
+static PyObject *__Pyx_GetBuiltinName(PyObject *name);
+
+static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name);
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw);
+#else
+#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw)
+#endif
+
+static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
+    Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found);
+
+static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name);
+
+static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], \
+    PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, \
+    const char* function_name);
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg);
+#endif
+
+static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg);
+
+static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb);
+static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb);
+
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause);
+
+#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \
+    (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \
+    __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) : \
+    (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) : \
+               __Pyx_GetItemInt_Generic(o, to_py_func(i))))
+#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \
+    (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \
+    __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) : \
+    (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL))
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck);
+#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck) \
+    (__Pyx_fits_Py_ssize_t(i, type, is_signed) ? \
+    __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) : \
+    (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL))
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck);
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j);
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
+                                                     int is_list, int wraparound, int boundscheck);
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func);
+#else
+#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL)
+#endif
+
+static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb);
+static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb);
+
+static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb);
+
+static void __Pyx_WriteUnraisable(const char *name, int clineno,
+                                  int lineno, const char *filename,
+                                  int full_traceback);
+
+static CYTHON_INLINE int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
+    const char *name, int exact);
+
+static CYTHON_INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed);
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) {
+    PyListObject* L = (PyListObject*) list;
+    Py_ssize_t len = Py_SIZE(list);
+    if (likely(L->allocated > len)) {
+        Py_INCREF(x);
+        PyList_SET_ITEM(list, len, x);
+        Py_SIZE(list) = len+1;
+        return 0;
+    }
+    return PyList_Append(list, x);
+}
+#else
+#define __Pyx_ListComp_Append(L,x) PyList_Append(L,x)
+#endif
+
+static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb);
+
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __Pyx_PyObject_DelAttrStr(o,n) __Pyx_PyObject_SetAttrStr(o,n,NULL)
+static CYTHON_INLINE int __Pyx_PyObject_SetAttrStr(PyObject* obj, PyObject* attr_name, PyObject* value) {
+    PyTypeObject* tp = Py_TYPE(obj);
+    if (likely(tp->tp_setattro))
+        return tp->tp_setattro(obj, attr_name, value);
+#if PY_MAJOR_VERSION < 3
+    if (likely(tp->tp_setattr))
+        return tp->tp_setattr(obj, PyString_AS_STRING(attr_name), value);
+#endif
+    return PyObject_SetAttr(obj, attr_name, value);
+}
+#else
+#define __Pyx_PyObject_DelAttrStr(o,n)   PyObject_DelAttr(o,n)
+#define __Pyx_PyObject_SetAttrStr(o,n,v) PyObject_SetAttr(o,n,v)
+#endif
+
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type);
+
+static double __Pyx__PyObject_AsDouble(PyObject* obj);
+#if CYTHON_COMPILING_IN_PYPY
+#define __Pyx_PyObject_AsDouble(obj) \
+(likely(PyFloat_CheckExact(obj)) ? PyFloat_AS_DOUBLE(obj) : \
+ likely(PyInt_CheckExact(obj)) ? \
+ PyFloat_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj))
+#else
+#define __Pyx_PyObject_AsDouble(obj) \
+((likely(PyFloat_CheckExact(obj))) ? \
+ PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj))
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
+    PyObject *value;
+    value = PyDict_GetItemWithError(d, key);
+    if (unlikely(!value)) {
+        if (!PyErr_Occurred()) {
+            PyObject* args = PyTuple_Pack(1, key);
+            if (likely(args))
+                PyErr_SetObject(PyExc_KeyError, args);
+            Py_XDECREF(args);
+        }
+        return NULL;
+    }
+    Py_INCREF(value);
+    return value;
+}
+#else
+    #define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key)
+#endif
+
+static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, traverseproc current_tp_traverse);
+
+static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_dealloc);
+
+#include <string.h>
+
+static int __Pyx_SetVtable(PyObject *dict, void *vtable);
+
+static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases);
+
+static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *qualname,
+                                           PyObject *mkw, PyObject *modname, PyObject *doc);
+static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict,
+                                      PyObject *mkw, int calculate_metaclass, int allow_py2_metaclass);
+
+static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type);
+
+#define __Pyx_CyFunction_USED 1
+#include <structmember.h>
+#define __Pyx_CYFUNCTION_STATICMETHOD  0x01
+#define __Pyx_CYFUNCTION_CLASSMETHOD   0x02
+#define __Pyx_CYFUNCTION_CCLASS        0x04
+#define __Pyx_CyFunction_GetClosure(f) \
+    (((__pyx_CyFunctionObject *) (f))->func_closure)
+#define __Pyx_CyFunction_GetClassObj(f) \
+    (((__pyx_CyFunctionObject *) (f))->func_classobj)
+#define __Pyx_CyFunction_Defaults(type, f) \
+    ((type *)(((__pyx_CyFunctionObject *) (f))->defaults))
+#define __Pyx_CyFunction_SetDefaultsGetter(f, g) \
+    ((__pyx_CyFunctionObject *) (f))->defaults_getter = (g)
+typedef struct {
+    PyCFunctionObject func;
+#if PY_VERSION_HEX < 0x030500A0
+    PyObject *func_weakreflist;
+#endif
+    PyObject *func_dict;
+    PyObject *func_name;
+    PyObject *func_qualname;
+    PyObject *func_doc;
+    PyObject *func_globals;
+    PyObject *func_code;
+    PyObject *func_closure;
+    PyObject *func_classobj;
+    void *defaults;
+    int defaults_pyobjects;
+    int flags;
+    PyObject *defaults_tuple;
+    PyObject *defaults_kwdict;
+    PyObject *(*defaults_getter)(PyObject *);
+    PyObject *func_annotations;
+} __pyx_CyFunctionObject;
+static PyTypeObject *__pyx_CyFunctionType = 0;
+#define __Pyx_CyFunction_NewEx(ml, flags, qualname, self, module, globals, code) \
+    __Pyx_CyFunction_New(__pyx_CyFunctionType, ml, flags, qualname, self, module, globals, code)
+static PyObject *__Pyx_CyFunction_New(PyTypeObject *, PyMethodDef *ml,
+                                      int flags, PyObject* qualname,
+                                      PyObject *self,
+                                      PyObject *module, PyObject *globals,
+                                      PyObject* code);
+static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *m,
+                                                         size_t size,
+                                                         int pyobjects);
+static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *m,
+                                                            PyObject *tuple);
+static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *m,
+                                                             PyObject *dict);
+static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *m,
+                                                              PyObject *dict);
+static int __Pyx_CyFunction_init(void);
+
+static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name);
+
+typedef struct {
+    int code_line;
+    PyCodeObject* code_object;
+} __Pyx_CodeObjectCacheEntry;
+struct __Pyx_CodeObjectCache {
+    int count;
+    int max_count;
+    __Pyx_CodeObjectCacheEntry* entries;
+};
+static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL};
+static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
+static PyCodeObject *__pyx_find_code_object(int code_line);
+static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
+
+static void __Pyx_AddTraceback(const char *funcname, int c_line,
+                               int py_line, const char *filename);
+
+#ifndef _ARRAYARRAY_H
+#define _ARRAYARRAY_H
+typedef struct arraydescr {
+    int typecode;
+    int itemsize;
+    PyObject * (*getitem)(struct arrayobject *, Py_ssize_t);
+    int (*setitem)(struct arrayobject *, Py_ssize_t, PyObject *);
+#if PY_MAJOR_VERSION >= 3
+    char *formats;
+#endif
+} arraydescr;
+struct arrayobject {
+    PyObject_HEAD
+    Py_ssize_t ob_size;
+    union {
+        char *ob_item;
+        float *as_floats;
+        double *as_doubles;
+        int *as_ints;
+        unsigned int *as_uints;
+        unsigned char *as_uchars;
+        signed char *as_schars;
+        char *as_chars;
+        unsigned long *as_ulongs;
+        long *as_longs;
+        short *as_shorts;
+        unsigned short *as_ushorts;
+        Py_UNICODE *as_pyunicodes;
+        void *as_voidptr;
+    } data;
+    Py_ssize_t allocated;
+    struct arraydescr *ob_descr;
+    PyObject *weakreflist;
+#if PY_MAJOR_VERSION >= 3
+        int ob_exports;
+#endif
+};
+#ifndef NO_NEWARRAY_INLINE
+static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t size,
+    struct arraydescr *descr) {
+    arrayobject *op;
+    size_t nbytes;
+    if (size < 0) {
+        PyErr_BadInternalCall();
+        return NULL;
+    }
+    nbytes = size * descr->itemsize;
+    if (nbytes / descr->itemsize != (size_t)size) {
+        return PyErr_NoMemory();
+    }
+    op = (arrayobject *) type->tp_alloc(type, 0);
+    if (op == NULL) {
+        return NULL;
+    }
+    op->ob_descr = descr;
+    op->allocated = size;
+    op->weakreflist = NULL;
+    op->ob_size = size;
+    if (size <= 0) {
+        op->data.ob_item = NULL;
+    }
+    else {
+        op->data.ob_item = PyMem_NEW(char, nbytes);
+        if (op->data.ob_item == NULL) {
+            Py_DECREF(op);
+            return PyErr_NoMemory();
+        }
+    }
+    return (PyObject *) op;
+}
+#else
+PyObject* newarrayobject(PyTypeObject *type, Py_ssize_t size,
+    struct arraydescr *descr);
+#endif
+static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) {
+    void *items = (void*) self->data.ob_item;
+    PyMem_Resize(items, char, (size_t)(n * self->ob_descr->itemsize));
+    if (items == NULL) {
+        PyErr_NoMemory();
+        return -1;
+    }
+    self->data.ob_item = (char*) items;
+    self->ob_size = n;
+    self->allocated = n;
+    return 0;
+}
+static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) {
+    void *items = (void*) self->data.ob_item;
+    Py_ssize_t newsize;
+    if (n < self->allocated) {
+        if (n*4 > self->allocated) {
+            self->ob_size = n;
+            return 0;
+        }
+    }
+    newsize = n  * 3 / 2 + 1;
+    PyMem_Resize(items, char, (size_t)(newsize * self->ob_descr->itemsize));
+    if (items == NULL) {
+        PyErr_NoMemory();
+        return -1;
+    }
+    self->data.ob_item = (char*) items;
+    self->ob_size = n;
+    self->allocated = newsize;
+    return 0;
+}
+#endif
+
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value);
+
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level);
+
+static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *);
+
+static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *);
+
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value);
+
+#ifndef __Pyx_CppExn2PyErr
+#include <new>
+#include <typeinfo>
+#include <stdexcept>
+#include <ios>
+static void __Pyx_CppExn2PyErr() {
+  try {
+    if (PyErr_Occurred())
+      ; // let the latest Python exn pass through and ignore the current one
+    else
+      throw;
+  } catch (const std::bad_alloc& exn) {
+    PyErr_SetString(PyExc_MemoryError, exn.what());
+  } catch (const std::bad_cast& exn) {
+    PyErr_SetString(PyExc_TypeError, exn.what());
+  } catch (const std::domain_error& exn) {
+    PyErr_SetString(PyExc_ValueError, exn.what());
+  } catch (const std::invalid_argument& exn) {
+    PyErr_SetString(PyExc_ValueError, exn.what());
+  } catch (const std::ios_base::failure& exn) {
+    PyErr_SetString(PyExc_IOError, exn.what());
+  } catch (const std::out_of_range& exn) {
+    PyErr_SetString(PyExc_IndexError, exn.what());
+  } catch (const std::overflow_error& exn) {
+    PyErr_SetString(PyExc_OverflowError, exn.what());
+  } catch (const std::range_error& exn) {
+    PyErr_SetString(PyExc_ArithmeticError, exn.what());
+  } catch (const std::underflow_error& exn) {
+    PyErr_SetString(PyExc_ArithmeticError, exn.what());
+  } catch (const std::exception& exn) {
+    PyErr_SetString(PyExc_RuntimeError, exn.what());
+  }
+  catch (...)
+  {
+    PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
+  }
+}
+#endif
+
+static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg);
+
+#define __Pyx_Generator_USED
+#include <structmember.h>
+#include <frameobject.h>
+typedef PyObject *(*__pyx_generator_body_t)(PyObject *, PyObject *);
+typedef struct {
+    PyObject_HEAD
+    __pyx_generator_body_t body;
+    PyObject *closure;
+    PyObject *exc_type;
+    PyObject *exc_value;
+    PyObject *exc_traceback;
+    PyObject *gi_weakreflist;
+    PyObject *classobj;
+    PyObject *yieldfrom;
+    PyObject *gi_name;
+    PyObject *gi_qualname;
+    int resume_label;
+    char is_running;
+} __pyx_GeneratorObject;
+static __pyx_GeneratorObject *__Pyx_Generator_New(__pyx_generator_body_t body,
+                                                  PyObject *closure, PyObject *name, PyObject *qualname);
+static int __pyx_Generator_init(void);
+static int __Pyx_Generator_clear(PyObject* self);
+#if 1 || PY_VERSION_HEX < 0x030300B0
+static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue);
+#else
+#define __Pyx_PyGen_FetchStopIterationValue(pvalue) PyGen_FetchStopIterationValue(pvalue)
+#endif
+
+static int __Pyx_check_binary_version(void);
+
+static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig);
+
+#if !defined(__Pyx_PyIdentifier_FromString)
+#if PY_MAJOR_VERSION < 3
+  #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s)
+#else
+  #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s)
+#endif
+#endif
+
+static PyObject *__Pyx_ImportModule(const char *name);
+
+static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name, size_t size, int strict);
+
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t);
+
+static PyObject *__pyx_f_7pymusic_4Port_null(struct __pyx_obj_7pymusic_Port *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
+static PyObject *__pyx_f_7pymusic_14EventInputPort_null(struct __pyx_obj_7pymusic_EventInputPort *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
+static PyObject *__pyx_f_7pymusic_16MessageInputPort_null(struct __pyx_obj_7pymusic_MessageInputPort *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
+static struct PyMPIIntracommObject *__pyx_f_7pymusic_5Setup_getcomm(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, int __pyx_skip_dispatch); /* proto*/
+static PyObject *__pyx_f_7pymusic_5Setup_null(struct __pyx_obj_7pymusic_Setup *__pyx_v_self); /* proto*/
+
+/* Module declarations from 'mpi4py.MPI' */
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Status = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Datatype = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Request = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Prequest = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Grequest = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Op = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Group = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Info = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Errhandler = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Comm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Intracomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Cartcomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Graphcomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Distgraphcomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Intercomm = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_Win = 0;
+static PyTypeObject *__pyx_ptype_6mpi4py_3MPI_File = 0;
+
+/* Module declarations from 'mpi4py.mpi_c' */
+
+/* Module declarations from 'libcpp' */
+
+/* Module declarations from 'libc.string' */
+
+/* Module declarations from 'libcpp.string' */
+
+/* Module declarations from 'cpython.ref' */
+
+/* Module declarations from 'music.pybuffer' */
+static PyTypeObject *__pyx_ptype_5music_8pybuffer_Buffer = 0;
+
+/* Module declarations from 'libc.stdlib' */
+
+/* Module declarations from 'cpython.version' */
+
+/* Module declarations from 'cpython.exc' */
+
+/* Module declarations from 'cpython.module' */
+
+/* Module declarations from 'cpython.mem' */
+
+/* Module declarations from 'cpython.tuple' */
+
+/* Module declarations from 'cpython.list' */
+
+/* Module declarations from 'libc.stdio' */
+
+/* Module declarations from 'cpython.object' */
+
+/* Module declarations from 'cpython.sequence' */
+
+/* Module declarations from 'cpython.mapping' */
+
+/* Module declarations from 'cpython.iterator' */
+
+/* Module declarations from '__builtin__' */
+
+/* Module declarations from 'cpython.type' */
+static PyTypeObject *__pyx_ptype_7cpython_4type_type = 0;
+
+/* Module declarations from 'cpython.number' */
+
+/* Module declarations from 'cpython.int' */
+
+/* Module declarations from '__builtin__' */
+
+/* Module declarations from 'cpython.bool' */
+static PyTypeObject *__pyx_ptype_7cpython_4bool_bool = 0;
+
+/* Module declarations from 'cpython.long' */
+
+/* Module declarations from 'cpython.float' */
+
+/* Module declarations from '__builtin__' */
+
+/* Module declarations from 'cpython.complex' */
+static PyTypeObject *__pyx_ptype_7cpython_7complex_complex = 0;
+
+/* Module declarations from 'cpython.string' */
+
+/* Module declarations from 'cpython.unicode' */
+
+/* Module declarations from 'cpython.dict' */
+
+/* Module declarations from 'cpython.instance' */
+
+/* Module declarations from 'cpython.function' */
+
+/* Module declarations from 'cpython.method' */
+
+/* Module declarations from 'cpython.weakref' */
+
+/* Module declarations from 'cpython.getargs' */
+
+/* Module declarations from 'cpython.pythread' */
+
+/* Module declarations from 'cpython.pystate' */
+
+/* Module declarations from 'cpython.cobject' */
+
+/* Module declarations from 'cpython.oldbuffer' */
+
+/* Module declarations from 'cpython.set' */
+
+/* Module declarations from 'cpython.buffer' */
+
+/* Module declarations from 'cpython.bytes' */
+
+/* Module declarations from 'cpython.pycapsule' */
+
+/* Module declarations from 'cpython' */
+
+/* Module declarations from 'array' */
+
+/* Module declarations from 'cpython.array' */
+static PyTypeObject *__pyx_ptype_7cpython_5array_array = 0;
+static CYTHON_INLINE int __pyx_f_7cpython_5array_extend_buffer(arrayobject *, char *, Py_ssize_t); /*proto*/
+
+/* Module declarations from 'pymusic' */
+static PyTypeObject *__pyx_ptype_7pymusic_Setup = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_Runtime = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_Port = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_ContInputPort = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_ContOutputPort = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_EventInputPort = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_EventOutputPort = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_MessageInputPort = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_MessageOutputPort = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_DataMap = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_IndexMap = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_EventHandler = 0;
+static PyTypeObject *__pyx_ptype_7pymusic_MessageHandler = 0;
+static PyTypeObject *__pyx_ptype_7pymusic__Index = 0;
+static PyTypeObject *__pyx_ptype_7pymusic___pyx_scope_struct____iter__ = 0;
+static __pyx_t_7pymusic_Args __pyx_f_7pymusic_argv_toc(PyObject *); /*proto*/
+static std::string __pyx_convert_string_from_py_std__string(PyObject *); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_convert_PyObject_string_to_py_std__string(std::string const &); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_convert_PyUnicode_string_to_py_std__string(std::string const &); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_convert_PyBytes_string_to_py_std__string(std::string const &); /*proto*/
+static CYTHON_INLINE PyObject *__pyx_convert_PyByteArray_string_to_py_std__string(std::string const &); /*proto*/
+#define __Pyx_MODULE_NAME "pymusic"
+int __pyx_module_is_main_pymusic = 0;
+
+/* Implementation of 'pymusic' */
+static PyObject *__pyx_builtin_Exception;
+static PyObject *__pyx_builtin_range;
+static PyObject *__pyx_builtin_xrange;
+static PyObject *__pyx_builtin_ValueError;
+static PyObject *__pyx_builtin_MemoryError;
+static PyObject *__pyx_pf_7pymusic_7NoWidth___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_15UndefinedConfig___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_var); /* proto */
+static PyObject *__pyx_pf_7pymusic_predictRank(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_argv); /* proto */
+static int __pyx_pf_7pymusic_4Port___cinit__(struct __pyx_obj_7pymusic_Port *__pyx_v_self); /* proto */
+static Py_hash_t __pyx_pf_7pymusic_4Port_2__hash__(struct __pyx_obj_7pymusic_Port *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_4Port_4null(struct __pyx_obj_7pymusic_Port *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_4Port_6isConnected(struct __pyx_obj_7pymusic_Port *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_4Port_8width(struct __pyx_obj_7pymusic_Port *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_13ContInputPort_map(struct __pyx_obj_7pymusic_ContInputPort *__pyx_v_self, PyObject *__pyx_v_data, int __pyx_v_base, PyObject *__pyx_v_perm, double __pyx_v_delay, bool __pyx_v_interpolate, int __pyx_v_maxBuffered); /* proto */
+static PyObject *__pyx_pf_7pymusic_14ContOutputPort_map(struct __pyx_obj_7pymusic_ContOutputPort *__pyx_v_self, PyObject *__pyx_v_data, int __pyx_v_base, PyObject *__pyx_v_perm, int __pyx_v_maxBuffered); /* proto */
+static int __pyx_pf_7pymusic_14EventInputPort___cinit__(struct __pyx_obj_7pymusic_EventInputPort *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_14EventInputPort_2null(struct __pyx_obj_7pymusic_EventInputPort *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_14EventInputPort_4map(struct __pyx_obj_7pymusic_EventInputPort *__pyx_v_self, PyObject *__pyx_v_func, MUSIC::Index::Type __pyx_v_t, double __pyx_v_accLatency, int __pyx_v_maxBuffered, PyObject *__pyx_v_perm, int __pyx_v_base, int __pyx_v_size); /* proto */
+static PyObject *__pyx_pf_7pymusic_15EventOutputPort_map(struct __pyx_obj_7pymusic_EventOutputPort *__pyx_v_self, MUSIC::Index::Type __pyx_v_t, int __pyx_v_maxBuffered, PyObject *__pyx_v_perm, int __pyx_v_base, int __pyx_v_size); /* proto */
+static PyObject *__pyx_pf_7pymusic_15EventOutputPort_2insertEvent(struct __pyx_obj_7pymusic_EventOutputPort *__pyx_v_self, double __pyx_v_time, int __pyx_v_index, CYTHON_UNUSED MUSIC::Index::Type __pyx_v_t); /* proto */
+static int __pyx_pf_7pymusic_16MessageInputPort___cinit__(struct __pyx_obj_7pymusic_MessageInputPort *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_16MessageInputPort_2null(struct __pyx_obj_7pymusic_MessageInputPort *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_16MessageInputPort_4map(struct __pyx_obj_7pymusic_MessageInputPort *__pyx_v_self, PyObject *__pyx_v_func, double __pyx_v_accLatency, int __pyx_v_maxBuffered, int __pyx_v_pickled); /* proto */
+static PyObject *__pyx_pf_7pymusic_17MessageOutputPort_map(struct __pyx_obj_7pymusic_MessageOutputPort *__pyx_v_self, int __pyx_v_maxBuffered, int __pyx_v_pickled); /* proto */
+static PyObject *__pyx_pf_7pymusic_17MessageOutputPort_2insertMessage(struct __pyx_obj_7pymusic_MessageOutputPort *__pyx_v_self, double __pyx_v_time, PyObject *__pyx_v_msg); /* proto */
+static int __pyx_pf_7pymusic_5Setup___cinit__(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, PyObject *__pyx_v_argv, PyObject *__pyx_v_required); /* proto */
+static void __pyx_pf_7pymusic_5Setup_2__dealloc__(struct __pyx_obj_7pymusic_Setup *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_4getcomm(struct __pyx_obj_7pymusic_Setup *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_6config(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_var); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_8publishContInput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_10publishContOutput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_12publishEventOutput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_14publishEventInput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_16publishMessageOutput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_18publishMessageInput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_20runtime(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, double __pyx_v_timestep); /* proto */
+static PyObject *__pyx_pf_7pymusic_5Setup_4comm___get__(struct __pyx_obj_7pymusic_Setup *__pyx_v_self); /* proto */
+static int __pyx_pf_7pymusic_7Runtime___cinit__(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self, struct __pyx_obj_7pymusic_Setup *__pyx_v_setup, double __pyx_v_h); /* proto */
+static void __pyx_pf_7pymusic_7Runtime_2__dealloc__(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_7Runtime_4time(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_7Runtime_6tick(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_7Runtime_8__iter__(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_7Runtime_4comm___get__(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self); /* proto */
+static int __pyx_pf_7pymusic_8IndexMap___cinit__(struct __pyx_obj_7pymusic_IndexMap *__pyx_v_self, PyObject *__pyx_v_perm, int __pyx_v_base, int __pyx_v_size); /* proto */
+static void __pyx_pf_7pymusic_8IndexMap_2__dealloc__(struct __pyx_obj_7pymusic_IndexMap *__pyx_v_self); /* proto */
+static int __pyx_pf_7pymusic_7DataMap___cinit__(struct __pyx_obj_7pymusic_DataMap *__pyx_v_self, struct __pyx_obj_5music_8pybuffer_Buffer *__pyx_v_buf, struct __pyx_obj_7pymusic_IndexMap *__pyx_v_index_map, int __pyx_v_index); /* proto */
+static void __pyx_pf_7pymusic_7DataMap_2__dealloc__(struct __pyx_obj_7pymusic_DataMap *__pyx_v_self); /* proto */
+static int __pyx_pf_7pymusic_12EventHandler___cinit__(struct __pyx_obj_7pymusic_EventHandler *__pyx_v_self, PyObject *__pyx_v_func, MUSIC::Index::Type __pyx_v_t); /* proto */
+static void __pyx_pf_7pymusic_12EventHandler_2__dealloc__(struct __pyx_obj_7pymusic_EventHandler *__pyx_v_self); /* proto */
+static int __pyx_pf_7pymusic_6_Index___cinit__(struct __pyx_obj_7pymusic__Index *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_6_Index_2tostr(struct __pyx_obj_7pymusic__Index *__pyx_v_self, int __pyx_v_index); /* proto */
+static PyObject *__pyx_pf_7pymusic_6_Index_6GLOBAL___get__(struct __pyx_obj_7pymusic__Index *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_6_Index_5LOCAL___get__(struct __pyx_obj_7pymusic__Index *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_7pymusic_6_Index_7backmap___get__(struct __pyx_obj_7pymusic__Index *__pyx_v_self); /* proto */
+static int __pyx_pf_7pymusic_14MessageHandler___cinit__(struct __pyx_obj_7pymusic_MessageHandler *__pyx_v_self, PyObject *__pyx_v_func, int __pyx_v_pickled); /* proto */
+static void __pyx_pf_7pymusic_14MessageHandler_2__dealloc__(struct __pyx_obj_7pymusic_MessageHandler *__pyx_v_self); /* proto */
+static int __pyx_pf_7cpython_5array_5array___getbuffer__(arrayobject *__pyx_v_self, Py_buffer *__pyx_v_info, CYTHON_UNUSED int __pyx_v_flags); /* proto */
+static void __pyx_pf_7cpython_5array_5array_2__releasebuffer__(CYTHON_UNUSED arrayobject *__pyx_v_self, Py_buffer *__pyx_v_info); /* proto */
+static PyObject *__pyx_tp_new_7pymusic_Setup(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_Runtime(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_Port(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_ContInputPort(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_ContOutputPort(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_EventInputPort(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_EventOutputPort(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_MessageInputPort(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_MessageOutputPort(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_DataMap(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_IndexMap(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_EventHandler(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic_MessageHandler(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic__Index(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static PyObject *__pyx_tp_new_7pymusic___pyx_scope_struct____iter__(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
+static char __pyx_k_h[] = "h";
+static char __pyx_k_i[] = "i";
+static char __pyx_k_r[] = "r";
+static char __pyx_k_t[] = "t";
+static char __pyx_k__3[] = "*";
+static char __pyx_k_MPI[] = "MPI";
+static char __pyx_k_buf[] = "buf";
+static char __pyx_k_doc[] = "__doc__";
+static char __pyx_k_msg[] = "msg";
+static char __pyx_k_ptr[] = "ptr";
+static char __pyx_k_sys[] = "sys";
+static char __pyx_k_var[] = "var";
+static char __pyx_k_args[] = "args";
+static char __pyx_k_argv[] = "argv";
+static char __pyx_k_base[] = "base";
+static char __pyx_k_data[] = "data";
+static char __pyx_k_func[] = "func";
+static char __pyx_k_init[] = "__init__";
+static char __pyx_k_iter[] = "__iter__";
+static char __pyx_k_main[] = "__main__";
+static char __pyx_k_null[] = "null";
+static char __pyx_k_perm[] = "perm";
+static char __pyx_k_self[] = "self";
+static char __pyx_k_send[] = "send";
+static char __pyx_k_size[] = "size";
+static char __pyx_k_test[] = "__test__";
+static char __pyx_k_time[] = "time";
+static char __pyx_k_Index[] = "Index";
+static char __pyx_k_LOCAL[] = "LOCAL";
+static char __pyx_k_array[] = "array";
+static char __pyx_k_close[] = "close";
+static char __pyx_k_delay[] = "delay";
+static char __pyx_k_dumps[] = "dumps";
+static char __pyx_k_index[] = "index";
+static char __pyx_k_loads[] = "loads";
+static char __pyx_k_range[] = "range";
+static char __pyx_k_setup[] = "setup";
+static char __pyx_k_throw[] = "throw";
+static char __pyx_k_Buffer[] = "Buffer";
+static char __pyx_k_GLOBAL[] = "GLOBAL";
+static char __pyx_k_encode[] = "encode";
+static char __pyx_k_format[] = "format";
+static char __pyx_k_import[] = "__import__";
+static char __pyx_k_module[] = "__module__";
+static char __pyx_k_pickle[] = "pickle";
+static char __pyx_k_xrange[] = "xrange";
+static char __pyx_k_NoWidth[] = "NoWidth";
+static char __pyx_k_cPickle[] = "cPickle";
+static char __pyx_k_getcomm[] = "getcomm";
+static char __pyx_k_pickled[] = "pickled";
+static char __pyx_k_prepare[] = "__prepare__";
+static char __pyx_k_pymusic[] = "pymusic";
+static char __pyx_k_qualname[] = "__qualname__";
+static char __pyx_k_required[] = "required";
+static char __pyx_k_COMM_NULL[] = "COMM_NULL";
+static char __pyx_k_Exception[] = "Exception";
+static char __pyx_k_index_map[] = "index_map";
+static char __pyx_k_metaclass[] = "__metaclass__";
+static char __pyx_k_MUSICError[] = "MUSICError";
+static char __pyx_k_ValueError[] = "ValueError";
+static char __pyx_k_accLatency[] = "accLatency";
+static char __pyx_k_mpi4py_MPI[] = "mpi4py.MPI";
+static char __pyx_k_pyx_vtable[] = "__pyx_vtable__";
+static char __pyx_k_MemoryError[] = "MemoryError";
+static char __pyx_k_interpolate[] = "interpolate";
+static char __pyx_k_maxBuffered[] = "maxBuffered";
+static char __pyx_k_predictRank[] = "predictRank";
+static char __pyx_k_NoWidth___init[] = "NoWidth.__init__";
+static char __pyx_k_Runtime___iter[] = "Runtime.__iter__";
+static char __pyx_k_music_pybuffer[] = "music.pybuffer";
+static char __pyx_k_UndefinedConfig[] = "UndefinedConfig";
+static char __pyx_k_HIGHEST_PROTOCOL[] = "HIGHEST_PROTOCOL";
+static char __pyx_k_No_width_defined[] = "No width defined";
+static char __pyx_k_argv_can_t_be_empty[] = "argv can't be empty";
+static char __pyx_k_UndefinedConfig___init[] = "UndefinedConfig.__init__";
+static char __pyx_k_couldn_t_allocate_argv[] = "couldn't allocate argv";
+static char __pyx_k_Config_variable_is_not_defined[] = "Config variable {} is not defined";
+static char __pyx_k_Thrown_if_Port_width_is_called[] = "\n    Thrown if Port.width() is called, and port doesn't\n    have a width defined.\n    ";
+static char __pyx_k_All_exceptions_in_pymusic_are_M[] = "\n    All exceptions in pymusic are MUSICError's\n    ";
+static char __pyx_k_Thrown_if_a_configuration_value[] = "\n    Thrown if a configuration value is requested\n    via Setup.config(varname) for a variable name\n    that has not been defined within the configuration.\n    ";
+static char __pyx_k_home_apeyser_Code_music_pymusic[] = "/home/apeyser/Code/music/pymusic/pymusic.pyx";
+static PyObject *__pyx_kp_s_All_exceptions_in_pymusic_are_M;
+static PyObject *__pyx_n_s_Buffer;
+static PyObject *__pyx_n_s_COMM_NULL;
+static PyObject *__pyx_kp_s_Config_variable_is_not_defined;
+static PyObject *__pyx_n_s_Exception;
+static PyObject *__pyx_n_s_GLOBAL;
+static PyObject *__pyx_n_s_HIGHEST_PROTOCOL;
+static PyObject *__pyx_n_s_Index;
+static PyObject *__pyx_n_s_LOCAL;
+static PyObject *__pyx_n_s_MPI;
+static PyObject *__pyx_n_s_MUSICError;
+static PyObject *__pyx_n_s_MemoryError;
+static PyObject *__pyx_n_s_NoWidth;
+static PyObject *__pyx_n_s_NoWidth___init;
+static PyObject *__pyx_kp_s_No_width_defined;
+static PyObject *__pyx_n_s_Runtime___iter;
+static PyObject *__pyx_kp_s_Thrown_if_Port_width_is_called;
+static PyObject *__pyx_kp_s_Thrown_if_a_configuration_value;
+static PyObject *__pyx_n_s_UndefinedConfig;
+static PyObject *__pyx_n_s_UndefinedConfig___init;
+static PyObject *__pyx_n_s_ValueError;
+static PyObject *__pyx_n_s__3;
+static PyObject *__pyx_n_s_accLatency;
+static PyObject *__pyx_n_s_args;
+static PyObject *__pyx_n_s_argv;
+static PyObject *__pyx_kp_s_argv_can_t_be_empty;
+static PyObject *__pyx_n_s_array;
+static PyObject *__pyx_n_s_base;
+static PyObject *__pyx_n_s_buf;
+static PyObject *__pyx_n_s_cPickle;
+static PyObject *__pyx_n_s_close;
+static PyObject *__pyx_kp_s_couldn_t_allocate_argv;
+static PyObject *__pyx_n_s_data;
+static PyObject *__pyx_n_s_delay;
+static PyObject *__pyx_n_s_doc;
+static PyObject *__pyx_n_s_dumps;
+static PyObject *__pyx_n_s_encode;
+static PyObject *__pyx_n_s_format;
+static PyObject *__pyx_n_s_func;
+static PyObject *__pyx_n_s_getcomm;
+static PyObject *__pyx_n_s_h;
+static PyObject *__pyx_kp_s_home_apeyser_Code_music_pymusic;
+static PyObject *__pyx_n_s_i;
+static PyObject *__pyx_n_s_import;
+static PyObject *__pyx_n_s_index;
+static PyObject *__pyx_n_s_index_map;
+static PyObject *__pyx_n_s_init;
+static PyObject *__pyx_n_s_interpolate;
+static PyObject *__pyx_n_s_iter;
+static PyObject *__pyx_n_s_loads;
+static PyObject *__pyx_n_s_main;
+static PyObject *__pyx_n_s_maxBuffered;
+static PyObject *__pyx_n_s_metaclass;
+static PyObject *__pyx_n_s_module;
+static PyObject *__pyx_n_s_mpi4py_MPI;
+static PyObject *__pyx_n_s_msg;
+static PyObject *__pyx_n_s_music_pybuffer;
+static PyObject *__pyx_n_s_null;
+static PyObject *__pyx_n_s_perm;
+static PyObject *__pyx_n_s_pickle;
+static PyObject *__pyx_n_s_pickled;
+static PyObject *__pyx_n_s_predictRank;
+static PyObject *__pyx_n_s_prepare;
+static PyObject *__pyx_n_s_ptr;
+static PyObject *__pyx_n_s_pymusic;
+static PyObject *__pyx_n_s_pyx_vtable;
+static PyObject *__pyx_n_s_qualname;
+static PyObject *__pyx_n_s_r;
+static PyObject *__pyx_n_s_range;
+static PyObject *__pyx_n_s_required;
+static PyObject *__pyx_n_s_self;
+static PyObject *__pyx_n_s_send;
+static PyObject *__pyx_n_s_setup;
+static PyObject *__pyx_n_s_size;
+static PyObject *__pyx_n_s_sys;
+static PyObject *__pyx_n_s_t;
+static PyObject *__pyx_n_s_test;
+static PyObject *__pyx_n_s_throw;
+static PyObject *__pyx_n_s_time;
+static PyObject *__pyx_n_s_var;
+static PyObject *__pyx_n_s_xrange;
+static PyObject *__pyx_tuple_;
+static PyObject *__pyx_tuple__2;
+static PyObject *__pyx_tuple__4;
+static PyObject *__pyx_tuple__6;
+static PyObject *__pyx_tuple__8;
+static PyObject *__pyx_codeobj__5;
+static PyObject *__pyx_codeobj__7;
+static PyObject *__pyx_codeobj__9;
+
+/* "pymusic.pyx":23
+ *     have a width defined.
+ *     """
+ *     def __init__(self):             # <<<<<<<<<<<<<<
+ *         MUSICError.__init__(self, "No width defined")
+ * 
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_7NoWidth_1__init__(PyObject *__pyx_self, PyObject *__pyx_v_self); /*proto*/
+static PyMethodDef __pyx_mdef_7pymusic_7NoWidth_1__init__ = {"__init__", (PyCFunction)__pyx_pw_7pymusic_7NoWidth_1__init__, METH_O, 0};
+static PyObject *__pyx_pw_7pymusic_7NoWidth_1__init__(PyObject *__pyx_self, PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_7NoWidth___init__(__pyx_self, ((PyObject *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_7NoWidth___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  Py_ssize_t __pyx_t_4;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__init__", 0);
+
+  /* "pymusic.pyx":24
+ *     """
+ *     def __init__(self):
+ *         MUSICError.__init__(self, "No width defined")             # <<<<<<<<<<<<<<
+ * 
+ * class UndefinedConfig(MUSICError):
+ */
+  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_MUSICError); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_init); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = NULL;
+  __pyx_t_4 = 0;
+  if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_2)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_2);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
+      __pyx_t_4 = 1;
+    }
+  }
+  __pyx_t_5 = PyTuple_New(2+__pyx_t_4); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  if (__pyx_t_2) {
+    PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2); __Pyx_GIVEREF(__pyx_t_2); __pyx_t_2 = NULL;
+  }
+  __Pyx_INCREF(__pyx_v_self);
+  PyTuple_SET_ITEM(__pyx_t_5, 0+__pyx_t_4, __pyx_v_self);
+  __Pyx_GIVEREF(__pyx_v_self);
+  __Pyx_INCREF(__pyx_kp_s_No_width_defined);
+  PyTuple_SET_ITEM(__pyx_t_5, 1+__pyx_t_4, __pyx_kp_s_No_width_defined);
+  __Pyx_GIVEREF(__pyx_kp_s_No_width_defined);
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":23
+ *     have a width defined.
+ *     """
+ *     def __init__(self):             # <<<<<<<<<<<<<<
+ *         MUSICError.__init__(self, "No width defined")
+ * 
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("pymusic.NoWidth.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":32
+ *     that has not been defined within the configuration.
+ *     """
+ *     def __init__(self, var):             # <<<<<<<<<<<<<<
+ *         MUSICError.__init__(
+ *             self,
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_15UndefinedConfig_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_7pymusic_15UndefinedConfig_1__init__ = {"__init__", (PyCFunction)__pyx_pw_7pymusic_15UndefinedConfig_1__init__, METH_VARARGS|METH_KEYWORDS, 0};
+static PyObject *__pyx_pw_7pymusic_15UndefinedConfig_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_self = 0;
+  PyObject *__pyx_v_var = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_var,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_var)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_self = values[0];
+    __pyx_v_var = values[1];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.UndefinedConfig.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_15UndefinedConfig___init__(__pyx_self, __pyx_v_self, __pyx_v_var);
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_15UndefinedConfig___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_var) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  Py_ssize_t __pyx_t_7;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__init__", 0);
+
+  /* "pymusic.pyx":33
+ *     """
+ *     def __init__(self, var):
+ *         MUSICError.__init__(             # <<<<<<<<<<<<<<
+ *             self,
+ *             "Config variable {} is not defined".
+ */
+  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_MUSICError); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_init); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":35
+ *         MUSICError.__init__(
+ *             self,
+ *             "Config variable {} is not defined".             # <<<<<<<<<<<<<<
+ *             format(var)
+ *         )
+ */
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_kp_s_Config_variable_is_not_defined, __pyx_n_s_format); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+
+  /* "pymusic.pyx":36
+ *             self,
+ *             "Config variable {} is not defined".
+ *             format(var)             # <<<<<<<<<<<<<<
+ *         )
+ * 
+ */
+  __pyx_t_5 = NULL;
+  if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(__pyx_t_4))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_4, function);
+    }
+  }
+  if (!__pyx_t_5) {
+    __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_var); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+  } else {
+    __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __Pyx_GIVEREF(__pyx_t_5); __pyx_t_5 = NULL;
+    __Pyx_INCREF(__pyx_v_var);
+    PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_v_var);
+    __Pyx_GIVEREF(__pyx_v_var);
+    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  }
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = NULL;
+  __pyx_t_7 = 0;
+  if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_4)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
+      __pyx_t_7 = 1;
+    }
+  }
+  __pyx_t_6 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
+  if (__pyx_t_4) {
+    PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4); __Pyx_GIVEREF(__pyx_t_4); __pyx_t_4 = NULL;
+  }
+  __Pyx_INCREF(__pyx_v_self);
+  PyTuple_SET_ITEM(__pyx_t_6, 0+__pyx_t_7, __pyx_v_self);
+  __Pyx_GIVEREF(__pyx_v_self);
+  PyTuple_SET_ITEM(__pyx_t_6, 1+__pyx_t_7, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_6, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":32
+ *     that has not been defined within the configuration.
+ *     """
+ *     def __init__(self, var):             # <<<<<<<<<<<<<<
+ *         MUSICError.__init__(
+ *             self,
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_AddTraceback("pymusic.UndefinedConfig.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":52
+ *     char** argv
+ * 
+ * cdef Args argv_toc(list argv):             # <<<<<<<<<<<<<<
+ *     """
+ *     Convert an argv python list to a correct C argv & argc
+ */
+
+static __pyx_t_7pymusic_Args __pyx_f_7pymusic_argv_toc(PyObject *__pyx_v_argv) {
+  __pyx_t_7pymusic_Args __pyx_v_r;
+  long __pyx_v_i;
+  PyObject *__pyx_v_s = NULL;
+  __pyx_t_7pymusic_Args __pyx_r;
+  __Pyx_RefNannyDeclarations
+  Py_ssize_t __pyx_t_1;
+  int __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
+  int __pyx_t_8;
+  long __pyx_t_9;
+  PyObject *__pyx_t_10 = NULL;
+  char *__pyx_t_11;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("argv_toc", 0);
+
+  /* "pymusic.pyx":58
+ *     """
+ *     cdef Args r
+ *     r.argc = len(argv)             # <<<<<<<<<<<<<<
+ *     if r.argc <= 0:
+ *         raise MUSICError("argv can't be empty")
+ */
+  if (unlikely(__pyx_v_argv == Py_None)) {
+    PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_1 = PyList_GET_SIZE(__pyx_v_argv); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_r.argc = __pyx_t_1;
+
+  /* "pymusic.pyx":59
+ *     cdef Args r
+ *     r.argc = len(argv)
+ *     if r.argc <= 0:             # <<<<<<<<<<<<<<
+ *         raise MUSICError("argv can't be empty")
+ * 
+ */
+  __pyx_t_2 = ((__pyx_v_r.argc <= 0) != 0);
+  if (__pyx_t_2) {
+
+    /* "pymusic.pyx":60
+ *     r.argc = len(argv)
+ *     if r.argc <= 0:
+ *         raise MUSICError("argv can't be empty")             # <<<<<<<<<<<<<<
+ * 
+ *     r.argv = <char**> malloc((r.argc+1) * sizeof(char*))
+ */
+    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_MUSICError); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+
+  /* "pymusic.pyx":62
+ *         raise MUSICError("argv can't be empty")
+ * 
+ *     r.argv = <char**> malloc((r.argc+1) * sizeof(char*))             # <<<<<<<<<<<<<<
+ *     if r.argv is NULL:
+ *         raise MUSICError("couldn't allocate argv")
+ */
+  __pyx_v_r.argv = ((char **)malloc(((__pyx_v_r.argc + 1) * (sizeof(char *)))));
+
+  /* "pymusic.pyx":63
+ * 
+ *     r.argv = <char**> malloc((r.argc+1) * sizeof(char*))
+ *     if r.argv is NULL:             # <<<<<<<<<<<<<<
+ *         raise MUSICError("couldn't allocate argv")
+ * 
+ */
+  __pyx_t_2 = ((__pyx_v_r.argv == NULL) != 0);
+  if (__pyx_t_2) {
+
+    /* "pymusic.pyx":64
+ *     r.argv = <char**> malloc((r.argc+1) * sizeof(char*))
+ *     if r.argv is NULL:
+ *         raise MUSICError("couldn't allocate argv")             # <<<<<<<<<<<<<<
+ * 
+ *     cdef string
+ */
+    __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_MUSICError); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+
+  /* "pymusic.pyx":67
+ * 
+ *     cdef string
+ *     try:             # <<<<<<<<<<<<<<
+ *         r.argv[r.argc] = NULL
+ *         for i in range(0, r.argc):
+ */
+  {
+    __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
+    __Pyx_XGOTREF(__pyx_t_5);
+    __Pyx_XGOTREF(__pyx_t_6);
+    __Pyx_XGOTREF(__pyx_t_7);
+    /*try:*/ {
+
+      /* "pymusic.pyx":68
+ *     cdef string
+ *     try:
+ *         r.argv[r.argc] = NULL             # <<<<<<<<<<<<<<
+ *         for i in range(0, r.argc):
+ *             s = argv[i].encode()
+ */
+      (__pyx_v_r.argv[__pyx_v_r.argc]) = NULL;
+
+      /* "pymusic.pyx":69
+ *     try:
+ *         r.argv[r.argc] = NULL
+ *         for i in range(0, r.argc):             # <<<<<<<<<<<<<<
+ *             s = argv[i].encode()
+ *             r.argv[i] = s
+ */
+      __pyx_t_8 = __pyx_v_r.argc;
+      for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
+        __pyx_v_i = __pyx_t_9;
+
+        /* "pymusic.pyx":70
+ *         r.argv[r.argc] = NULL
+ *         for i in range(0, r.argc):
+ *             s = argv[i].encode()             # <<<<<<<<<<<<<<
+ *             r.argv[i] = s
+ *         return r
+ */
+        if (unlikely(__pyx_v_argv == Py_None)) {
+          PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
+          {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L5_error;}
+        }
+        __pyx_t_4 = __Pyx_GetItemInt_List(__pyx_v_argv, __pyx_v_i, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(__pyx_t_4 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L5_error;};
+        __Pyx_GOTREF(__pyx_t_4);
+        __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_encode); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L5_error;}
+        __Pyx_GOTREF(__pyx_t_10);
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_4 = NULL;
+        if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(__pyx_t_10))) {
+          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_10);
+          if (likely(__pyx_t_4)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10);
+            __Pyx_INCREF(__pyx_t_4);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_10, function);
+          }
+        }
+        if (__pyx_t_4) {
+          __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_10, __pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L5_error;}
+          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        } else {
+          __pyx_t_3 = __Pyx_PyObject_CallNoArg(__pyx_t_10); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L5_error;}
+        }
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_s, __pyx_t_3);
+        __pyx_t_3 = 0;
+
+        /* "pymusic.pyx":71
+ *         for i in range(0, r.argc):
+ *             s = argv[i].encode()
+ *             r.argv[i] = s             # <<<<<<<<<<<<<<
+ *         return r
+ *     except:
+ */
+        __pyx_t_11 = __Pyx_PyObject_AsString(__pyx_v_s); if (unlikely((!__pyx_t_11) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L5_error;}
+        (__pyx_v_r.argv[__pyx_v_i]) = __pyx_t_11;
+      }
+
+      /* "pymusic.pyx":72
+ *             s = argv[i].encode()
+ *             r.argv[i] = s
+ *         return r             # <<<<<<<<<<<<<<
+ *     except:
+ *         free(r.argv)
+ */
+      __pyx_r = __pyx_v_r;
+      goto __pyx_L9_try_return;
+    }
+    __pyx_L5_error:;
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+    /* "pymusic.pyx":73
+ *             r.argv[i] = s
+ *         return r
+ *     except:             # <<<<<<<<<<<<<<
+ *         free(r.argv)
+ *         raise
+ */
+    /*except:*/ {
+      __Pyx_AddTraceback("pymusic.argv_toc", __pyx_clineno, __pyx_lineno, __pyx_filename);
+      if (__Pyx_GetException(&__pyx_t_3, &__pyx_t_10, &__pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L7_except_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_GOTREF(__pyx_t_10);
+      __Pyx_GOTREF(__pyx_t_4);
+
+      /* "pymusic.pyx":74
+ *         return r
+ *     except:
+ *         free(r.argv)             # <<<<<<<<<<<<<<
+ *         raise
+ * 
+ */
+      free(__pyx_v_r.argv);
+
+      /* "pymusic.pyx":75
+ *     except:
+ *         free(r.argv)
+ *         raise             # <<<<<<<<<<<<<<
+ * 
+ * ###########################################################
+ */
+      __Pyx_GIVEREF(__pyx_t_3);
+      __Pyx_GIVEREF(__pyx_t_10);
+      __Pyx_XGIVEREF(__pyx_t_4);
+      __Pyx_ErrRestore(__pyx_t_3, __pyx_t_10, __pyx_t_4);
+      __pyx_t_3 = 0; __pyx_t_10 = 0; __pyx_t_4 = 0; 
+      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L7_except_error;}
+    }
+    __pyx_L7_except_error:;
+    __Pyx_XGIVEREF(__pyx_t_5);
+    __Pyx_XGIVEREF(__pyx_t_6);
+    __Pyx_XGIVEREF(__pyx_t_7);
+    __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7);
+    goto __pyx_L1_error;
+    __pyx_L9_try_return:;
+    __Pyx_XGIVEREF(__pyx_t_5);
+    __Pyx_XGIVEREF(__pyx_t_6);
+    __Pyx_XGIVEREF(__pyx_t_7);
+    __Pyx_ExceptionReset(__pyx_t_5, __pyx_t_6, __pyx_t_7);
+    goto __pyx_L0;
+  }
+
+  /* "pymusic.pyx":52
+ *     char** argv
+ * 
+ * cdef Args argv_toc(list argv):             # <<<<<<<<<<<<<<
+ *     """
+ *     Convert an argv python list to a correct C argv & argc
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_10);
+  __Pyx_WriteUnraisable("pymusic.argv_toc", __pyx_clineno, __pyx_lineno, __pyx_filename, 0);
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_s);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":79
+ * ###########################################################
+ * 
+ * def predictRank(list argv=None):             # <<<<<<<<<<<<<<
+ *     """
+ *     Map into mpidep/predict_rank for config methods.
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_1predictRank(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7pymusic_predictRank[] = "\n    Map into mpidep/predict_rank for config methods.\n    AP: What is this really used for?\n    ";
+static PyMethodDef __pyx_mdef_7pymusic_1predictRank = {"predictRank", (PyCFunction)__pyx_pw_7pymusic_1predictRank, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7pymusic_predictRank};
+static PyObject *__pyx_pw_7pymusic_1predictRank(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_argv = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("predictRank (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_argv,0};
+    PyObject* values[1] = {0};
+    values[0] = ((PyObject*)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_argv);
+          if (value) { values[0] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "predictRank") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_argv = ((PyObject*)values[0]);
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("predictRank", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.predictRank", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_argv), (&PyList_Type), 1, "argv", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_7pymusic_predictRank(__pyx_self, __pyx_v_argv);
+
+  /* function exit code */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_predictRank(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_argv) {
+  __pyx_t_7pymusic_Args __pyx_v_r;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("predictRank", 0);
+
+  /* "pymusic.pyx":84
+ *     AP: What is this really used for?
+ *     """
+ *     cdef Args r = argv_toc(argv if argv is not None else             # <<<<<<<<<<<<<<
+ *                            sys.argv)
+ *     return CPredictRank(r.argc, r.argv)
+ */
+  __pyx_t_2 = (__pyx_v_argv != ((PyObject*)Py_None));
+  if ((__pyx_t_2 != 0)) {
+    __Pyx_INCREF(__pyx_v_argv);
+    __pyx_t_1 = __pyx_v_argv;
+  } else {
+
+    /* "pymusic.pyx":85
+ *     """
+ *     cdef Args r = argv_toc(argv if argv is not None else
+ *                            sys.argv)             # <<<<<<<<<<<<<<
+ *     return CPredictRank(r.argc, r.argv)
+ * 
+ */
+    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_sys); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_argv); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (!(likely(PyList_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_t_4)->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __pyx_t_4;
+    __pyx_t_4 = 0;
+  }
+
+  /* "pymusic.pyx":84
+ *     AP: What is this really used for?
+ *     """
+ *     cdef Args r = argv_toc(argv if argv is not None else             # <<<<<<<<<<<<<<
+ *                            sys.argv)
+ *     return CPredictRank(r.argc, r.argv)
+ */
+  __pyx_v_r = __pyx_f_7pymusic_argv_toc(((PyObject*)__pyx_t_1));
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":86
+ *     cdef Args r = argv_toc(argv if argv is not None else
+ *                            sys.argv)
+ *     return CPredictRank(r.argc, r.argv)             # <<<<<<<<<<<<<<
+ * 
+ * ###########################################################
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_int(MUSIC::predictRank(__pyx_v_r.argc, __pyx_v_r.argv)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":79
+ * ###########################################################
+ * 
+ * def predictRank(list argv=None):             # <<<<<<<<<<<<<<
+ *     """
+ *     Map into mpidep/predict_rank for config methods.
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("pymusic.predictRank", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":99
+ *     container.
+ *     """
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         When a Port object is created, it needs to have an underlying
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_4Port_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_4Port_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) {
+    __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;}
+  if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__cinit__", 0))) return -1;
+  __pyx_r = __pyx_pf_7pymusic_4Port___cinit__(((struct __pyx_obj_7pymusic_Port *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_4Port___cinit__(struct __pyx_obj_7pymusic_Port *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":104
+ *         C++ class assigned to ptr from a Setup.publish* method.
+ *         """
+ *         self.ptr = NULL             # <<<<<<<<<<<<<<
+ * 
+ *     def __hash__(self):
+ */
+  __pyx_v_self->ptr = NULL;
+
+  /* "pymusic.pyx":99
+ *     container.
+ *     """
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         When a Port object is created, it needs to have an underlying
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":106
+ *         self.ptr = NULL
+ * 
+ *     def __hash__(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Hash function: pointer value % to an int.
+ */
+
+/* Python wrapper */
+static Py_hash_t __pyx_pw_7pymusic_4Port_3__hash__(PyObject *__pyx_v_self); /*proto*/
+static char __pyx_doc_7pymusic_4Port_2__hash__[] = "\n        Hash function: pointer value % to an int.\n        ";
+#if CYTHON_COMPILING_IN_CPYTHON
+struct wrapperbase __pyx_wrapperbase_7pymusic_4Port_2__hash__;
+#endif
+static Py_hash_t __pyx_pw_7pymusic_4Port_3__hash__(PyObject *__pyx_v_self) {
+  Py_hash_t __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__hash__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_4Port_2__hash__(((struct __pyx_obj_7pymusic_Port *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static Py_hash_t __pyx_pf_7pymusic_4Port_2__hash__(struct __pyx_obj_7pymusic_Port *__pyx_v_self) {
+  Py_hash_t __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__hash__", 0);
+
+  /* "pymusic.pyx":110
+ *         Hash function: pointer value % to an int.
+ *         """
+ *         return <int><size_t> self.ptr             # <<<<<<<<<<<<<<
+ * 
+ *     cpdef null(self):
+ */
+  __pyx_r = ((int)((size_t)__pyx_v_self->ptr));
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":106
+ *         self.ptr = NULL
+ * 
+ *     def __hash__(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Hash function: pointer value % to an int.
+ */
+
+  /* function exit code */
+  __pyx_L0:;
+  if (unlikely(__pyx_r == -1) && !PyErr_Occurred()) __pyx_r = -2;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":112
+ *         return <int><size_t> self.ptr
+ * 
+ *     cpdef null(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         When Setup or Runtime no longer needs ports and so may deallocate
+ */
+
+static PyObject *__pyx_pw_7pymusic_4Port_5null(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_f_7pymusic_4Port_null(struct __pyx_obj_7pymusic_Port *__pyx_v_self, int __pyx_skip_dispatch) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("null", 0);
+  /* Check if called by wrapper */
+  if (unlikely(__pyx_skip_dispatch)) ;
+  /* Check if overridden in Python */
+  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
+    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_null); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_7pymusic_4Port_5null)) {
+      __Pyx_XDECREF(__pyx_r);
+      __Pyx_INCREF(__pyx_t_1);
+      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+      if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+        if (likely(__pyx_t_4)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_4);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_3, function);
+        }
+      }
+      if (__pyx_t_4) {
+        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      } else {
+        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      }
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_r = __pyx_t_2;
+      __pyx_t_2 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      goto __pyx_L0;
+    }
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  }
+
+  /* "pymusic.pyx":119
+ *         the descendants
+ *         """
+ *         self.ptr = NULL             # <<<<<<<<<<<<<<
+ * 
+ *     def isConnected(self):
+ */
+  __pyx_v_self->ptr = NULL;
+
+  /* "pymusic.pyx":112
+ *         return <int><size_t> self.ptr
+ * 
+ *     cpdef null(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         When Setup or Runtime no longer needs ports and so may deallocate
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("pymusic.Port.null", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_4Port_5null(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_7pymusic_4Port_4null[] = "\n        When Setup or Runtime no longer needs ports and so may deallocate\n        them, we first must clear the references to them here. This\n        may be overridden to give up references to other members by\n        the descendants\n        ";
+static PyObject *__pyx_pw_7pymusic_4Port_5null(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("null (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_4Port_4null(((struct __pyx_obj_7pymusic_Port *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_4Port_4null(struct __pyx_obj_7pymusic_Port *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("null", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __pyx_f_7pymusic_4Port_null(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Port.null", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":121
+ *         self.ptr = NULL
+ * 
+ *     def isConnected(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         return True iff the port is actually connected via the config
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_4Port_7isConnected(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_7pymusic_4Port_6isConnected[] = "\n        return True iff the port is actually connected via the config\n        file.\n        ";
+static PyObject *__pyx_pw_7pymusic_4Port_7isConnected(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("isConnected (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_4Port_6isConnected(((struct __pyx_obj_7pymusic_Port *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_4Port_6isConnected(struct __pyx_obj_7pymusic_Port *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("isConnected", 0);
+
+  /* "pymusic.pyx":126
+ *         file.
+ *         """
+ *         return self.ptr.isConnected()             # <<<<<<<<<<<<<<
+ * 
+ *     def width(self):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_self->ptr->isConnected()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":121
+ *         self.ptr = NULL
+ * 
+ *     def isConnected(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         return True iff the port is actually connected via the config
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Port.isConnected", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":128
+ *         return self.ptr.isConnected()
+ * 
+ *     def width(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Returns the width set in the MUSIC config file
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_4Port_9width(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_7pymusic_4Port_8width[] = "\n        Returns the width set in the MUSIC config file\n        which defines the number of indices transferred\n        along this port. If no width is defined, raise a NoWidth\n        exception.\n        ";
+static PyObject *__pyx_pw_7pymusic_4Port_9width(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("width (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_4Port_8width(((struct __pyx_obj_7pymusic_Port *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_4Port_8width(struct __pyx_obj_7pymusic_Port *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("width", 0);
+
+  /* "pymusic.pyx":135
+ *         exception.
+ *         """
+ *         if not self.ptr.hasWidth(): raise NoWidth()             # <<<<<<<<<<<<<<
+ *         return self.ptr.width()
+ * 
+ */
+  __pyx_t_1 = ((!(__pyx_v_self->ptr->hasWidth() != 0)) != 0);
+  if (__pyx_t_1) {
+    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_NoWidth); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    if (__pyx_t_4) {
+      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    } else {
+      __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+
+  /* "pymusic.pyx":136
+ *         """
+ *         if not self.ptr.hasWidth(): raise NoWidth()
+ *         return self.ptr.width()             # <<<<<<<<<<<<<<
+ * 
+ * cdef class ContInputPort(Port):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_self->ptr->width()); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_r = __pyx_t_2;
+  __pyx_t_2 = 0;
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":128
+ *         return self.ptr.isConnected()
+ * 
+ *     def width(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Returns the width set in the MUSIC config file
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("pymusic.Port.width", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":144
+ *     Setup.publishContInputPort(portname).
+ *     """
+ *     def map(self,             # <<<<<<<<<<<<<<
+ *             object data,
+ *             int base=0,
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_13ContInputPort_1map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7pymusic_13ContInputPort_map[] = "\n        map data as source for this port. (Can you do a multiple mapping?)\n\n        object data: object to be shared that has a buffer interface.\n                     That interface needs to be contiguous formed of\n                     simple items that can be mapped to simple MPI\n                     data types.\n        int base (=0), object perm (=None): used to construct an\n                     IndexMap (with number of items in data). See that\n                     class for more information. Defines mapping for data\n                     between this input source and the output sinks.\n        double delay (=0): this is the delay of measurement relative\n                           to \"something\" which I haven't been able to\n                           figure out yet --- needs to be explained.\n        interpolate (=True): whether to do a linear interpolation of\n                             the values that are being delayed. Once\n                             again, needs to be better explained.\n        maxBuffered (=-1): buffer up to maxBuffered ticks. If -1, use\n                           a \"reasonable value\" (\077\077?).  What does this\n                           mean on the input side?\n        ";
+static PyObject *__pyx_pw_7pymusic_13ContInputPort_1map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_data = 0;
+  int __pyx_v_base;
+  PyObject *__pyx_v_perm = 0;
+  double __pyx_v_delay;
+  bool __pyx_v_interpolate;
+  int __pyx_v_maxBuffered;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("map (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_data,&__pyx_n_s_base,&__pyx_n_s_perm,&__pyx_n_s_delay,&__pyx_n_s_interpolate,&__pyx_n_s_maxBuffered,0};
+    PyObject* values[6] = {0,0,0,0,0,0};
+
+    /* "pymusic.pyx":147
+ *             object data,
+ *             int base=0,
+ *             object perm=None,             # <<<<<<<<<<<<<<
+ *             double delay=0,
+ *             cbool interpolate=True,
+ */
+    values[2] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_data)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_base);
+          if (value) { values[1] = value; kw_args--; }
+        }
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_perm);
+          if (value) { values[2] = value; kw_args--; }
+        }
+        case  3:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_delay);
+          if (value) { values[3] = value; kw_args--; }
+        }
+        case  4:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_interpolate);
+          if (value) { values[4] = value; kw_args--; }
+        }
+        case  5:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_maxBuffered);
+          if (value) { values[5] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "map") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_data = values[0];
+    if (values[1]) {
+      __pyx_v_base = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_base == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_base = ((int)0);
+    }
+    __pyx_v_perm = values[2];
+    if (values[3]) {
+      __pyx_v_delay = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_delay == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_delay = ((double)0.0);
+    }
+    if (values[4]) {
+      __pyx_v_interpolate = __Pyx_PyObject_IsTrue(values[4]); if (unlikely((__pyx_v_interpolate == (bool)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+
+      /* "pymusic.pyx":149
+ *             object perm=None,
+ *             double delay=0,
+ *             cbool interpolate=True,             # <<<<<<<<<<<<<<
+ *             int maxBuffered=-1):
+ *         """
+ */
+      __pyx_v_interpolate = ((bool)1);
+    }
+    if (values[5]) {
+      __pyx_v_maxBuffered = __Pyx_PyInt_As_int(values[5]); if (unlikely((__pyx_v_maxBuffered == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_maxBuffered = ((int)-1);
+    }
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("map", 0, 1, 6, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.ContInputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_13ContInputPort_map(((struct __pyx_obj_7pymusic_ContInputPort *)__pyx_v_self), __pyx_v_data, __pyx_v_base, __pyx_v_perm, __pyx_v_delay, __pyx_v_interpolate, __pyx_v_maxBuffered);
+
+  /* "pymusic.pyx":144
+ *     Setup.publishContInputPort(portname).
+ *     """
+ *     def map(self,             # <<<<<<<<<<<<<<
+ *             object data,
+ *             int base=0,
+ */
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_13ContInputPort_map(struct __pyx_obj_7pymusic_ContInputPort *__pyx_v_self, PyObject *__pyx_v_data, int __pyx_v_base, PyObject *__pyx_v_perm, double __pyx_v_delay, bool __pyx_v_interpolate, int __pyx_v_maxBuffered) {
+  struct __pyx_obj_5music_8pybuffer_Buffer *__pyx_v_buf = 0;
+  struct __pyx_obj_7pymusic_IndexMap *__pyx_v_imap = 0;
+  struct __pyx_obj_7pymusic_DataMap *__pyx_v_d = 0;
+  MUSIC::ContInputPort *__pyx_v_ptr;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("map", 0);
+
+  /* "pymusic.pyx":172
+ *                            mean on the input side?
+ *         """
+ *         cdef Buffer buf = Buffer(data)             # <<<<<<<<<<<<<<
+ *         cdef IndexMap imap = IndexMap(perm, base, buf.items)
+ *         cdef DataMap d = DataMap(buf, imap)
+ */
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_data);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_data);
+  __Pyx_GIVEREF(__pyx_v_data);
+  __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_5music_8pybuffer_Buffer)), __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)__pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":173
+ *         """
+ *         cdef Buffer buf = Buffer(data)
+ *         cdef IndexMap imap = IndexMap(perm, base, buf.items)             # <<<<<<<<<<<<<<
+ *         cdef DataMap d = DataMap(buf, imap)
+ *         cdef CContInputPort* ptr = dc_CContInputPort(self.ptr)
+ */
+  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_base); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_1 = PyInt_FromSsize_t(__pyx_v_buf->items); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_perm);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_perm);
+  __Pyx_GIVEREF(__pyx_v_perm);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_2 = 0;
+  __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_IndexMap)), __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_imap = ((struct __pyx_obj_7pymusic_IndexMap *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":174
+ *         cdef Buffer buf = Buffer(data)
+ *         cdef IndexMap imap = IndexMap(perm, base, buf.items)
+ *         cdef DataMap d = DataMap(buf, imap)             # <<<<<<<<<<<<<<
+ *         cdef CContInputPort* ptr = dc_CContInputPort(self.ptr)
+ *         mapImpl(ptr, d.ptr, delay, maxBuffered, interpolate)
+ */
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(((PyObject *)__pyx_v_buf));
+  PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_buf));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_buf));
+  __Pyx_INCREF(((PyObject *)__pyx_v_imap));
+  PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_v_imap));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_imap));
+  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_DataMap)), __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_d = ((struct __pyx_obj_7pymusic_DataMap *)__pyx_t_3);
+  __pyx_t_3 = 0;
+
+  /* "pymusic.pyx":175
+ *         cdef IndexMap imap = IndexMap(perm, base, buf.items)
+ *         cdef DataMap d = DataMap(buf, imap)
+ *         cdef CContInputPort* ptr = dc_CContInputPort(self.ptr)             # <<<<<<<<<<<<<<
+ *         mapImpl(ptr, d.ptr, delay, maxBuffered, interpolate)
+ * 
+ */
+  __pyx_v_ptr = dynamic_cast<MUSIC::ContInputPort*>(__pyx_v_self->__pyx_base.ptr);
+
+  /* "pymusic.pyx":176
+ *         cdef DataMap d = DataMap(buf, imap)
+ *         cdef CContInputPort* ptr = dc_CContInputPort(self.ptr)
+ *         mapImpl(ptr, d.ptr, delay, maxBuffered, interpolate)             # <<<<<<<<<<<<<<
+ * 
+ * cdef class ContOutputPort(Port):
+ */
+  MUSIC::Implementer::mapImpl(__pyx_v_ptr, __pyx_v_d->ptr, __pyx_v_delay, __pyx_v_maxBuffered, __pyx_v_interpolate);
+
+  /* "pymusic.pyx":144
+ *     Setup.publishContInputPort(portname).
+ *     """
+ *     def map(self,             # <<<<<<<<<<<<<<
+ *             object data,
+ *             int base=0,
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("pymusic.ContInputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_buf);
+  __Pyx_XDECREF((PyObject *)__pyx_v_imap);
+  __Pyx_XDECREF((PyObject *)__pyx_v_d);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":184
+ *     Setup.publishContOutputPort(portname).
+ *     """
+ *     def map(self, object data,             # <<<<<<<<<<<<<<
+ *             int base=0, object perm=None,
+ *             int maxBuffered=-1):
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_14ContOutputPort_1map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7pymusic_14ContOutputPort_map[] = "\n        map data as sink for this port. (Can you do a multiple mapping?)\n\n        object data: object to be shared that has a buffer interface.\n                     That interface needs to be contiguous formed of\n                     simple items that can be mapped to simple MPI\n                     data types.\n        int base (=0), object perm (=None): used to construct an\n                     IndexMap (with number of items in data). See that\n                     class for more information. Defines mapping for data\n                     between this input source and the output sinks.\n        maxBuffered (=-1): buffer up to maxBuffered ticks. If -1, use\n                     a \"reasonable value\" (\077\077?).\n        ";
+static PyObject *__pyx_pw_7pymusic_14ContOutputPort_1map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_data = 0;
+  int __pyx_v_base;
+  PyObject *__pyx_v_perm = 0;
+  int __pyx_v_maxBuffered;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("map (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_data,&__pyx_n_s_base,&__pyx_n_s_perm,&__pyx_n_s_maxBuffered,0};
+    PyObject* values[4] = {0,0,0,0};
+
+    /* "pymusic.pyx":185
+ *     """
+ *     def map(self, object data,
+ *             int base=0, object perm=None,             # <<<<<<<<<<<<<<
+ *             int maxBuffered=-1):
+ *         """
+ */
+    values[2] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_data)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_base);
+          if (value) { values[1] = value; kw_args--; }
+        }
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_perm);
+          if (value) { values[2] = value; kw_args--; }
+        }
+        case  3:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_maxBuffered);
+          if (value) { values[3] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "map") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_data = values[0];
+    if (values[1]) {
+      __pyx_v_base = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_base == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_base = ((int)0);
+    }
+    __pyx_v_perm = values[2];
+    if (values[3]) {
+      __pyx_v_maxBuffered = __Pyx_PyInt_As_int(values[3]); if (unlikely((__pyx_v_maxBuffered == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_maxBuffered = ((int)-1);
+    }
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("map", 0, 1, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.ContOutputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_14ContOutputPort_map(((struct __pyx_obj_7pymusic_ContOutputPort *)__pyx_v_self), __pyx_v_data, __pyx_v_base, __pyx_v_perm, __pyx_v_maxBuffered);
+
+  /* "pymusic.pyx":184
+ *     Setup.publishContOutputPort(portname).
+ *     """
+ *     def map(self, object data,             # <<<<<<<<<<<<<<
+ *             int base=0, object perm=None,
+ *             int maxBuffered=-1):
+ */
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_14ContOutputPort_map(struct __pyx_obj_7pymusic_ContOutputPort *__pyx_v_self, PyObject *__pyx_v_data, int __pyx_v_base, PyObject *__pyx_v_perm, int __pyx_v_maxBuffered) {
+  struct __pyx_obj_5music_8pybuffer_Buffer *__pyx_v_buf = 0;
+  struct __pyx_obj_7pymusic_IndexMap *__pyx_v_imap = 0;
+  struct __pyx_obj_7pymusic_DataMap *__pyx_v_d = 0;
+  MUSIC::ContOutputPort *__pyx_v_ptr;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("map", 0);
+
+  /* "pymusic.pyx":201
+ *                      a "reasonable value" (???).
+ *         """
+ *         cdef Buffer buf = Buffer(data)             # <<<<<<<<<<<<<<
+ *         cdef IndexMap imap = IndexMap(perm, base, buf.items)
+ *         cdef DataMap d = DataMap(buf, imap)
+ */
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_data);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_data);
+  __Pyx_GIVEREF(__pyx_v_data);
+  __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_5music_8pybuffer_Buffer)), __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)__pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":202
+ *         """
+ *         cdef Buffer buf = Buffer(data)
+ *         cdef IndexMap imap = IndexMap(perm, base, buf.items)             # <<<<<<<<<<<<<<
+ *         cdef DataMap d = DataMap(buf, imap)
+ *         cdef CContOutputPort* ptr = dc_CContOutputPort(self.ptr)
+ */
+  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_base); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_1 = PyInt_FromSsize_t(__pyx_v_buf->items); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_perm);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_perm);
+  __Pyx_GIVEREF(__pyx_v_perm);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_2 = 0;
+  __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_IndexMap)), __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_imap = ((struct __pyx_obj_7pymusic_IndexMap *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":203
+ *         cdef Buffer buf = Buffer(data)
+ *         cdef IndexMap imap = IndexMap(perm, base, buf.items)
+ *         cdef DataMap d = DataMap(buf, imap)             # <<<<<<<<<<<<<<
+ *         cdef CContOutputPort* ptr = dc_CContOutputPort(self.ptr)
+ *         mapImpl(ptr, d.ptr, maxBuffered)
+ */
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(((PyObject *)__pyx_v_buf));
+  PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_buf));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_buf));
+  __Pyx_INCREF(((PyObject *)__pyx_v_imap));
+  PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_v_imap));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_imap));
+  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_DataMap)), __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_d = ((struct __pyx_obj_7pymusic_DataMap *)__pyx_t_3);
+  __pyx_t_3 = 0;
+
+  /* "pymusic.pyx":204
+ *         cdef IndexMap imap = IndexMap(perm, base, buf.items)
+ *         cdef DataMap d = DataMap(buf, imap)
+ *         cdef CContOutputPort* ptr = dc_CContOutputPort(self.ptr)             # <<<<<<<<<<<<<<
+ *         mapImpl(ptr, d.ptr, maxBuffered)
+ * 
+ */
+  __pyx_v_ptr = dynamic_cast<MUSIC::ContOutputPort*>(__pyx_v_self->__pyx_base.ptr);
+
+  /* "pymusic.pyx":205
+ *         cdef DataMap d = DataMap(buf, imap)
+ *         cdef CContOutputPort* ptr = dc_CContOutputPort(self.ptr)
+ *         mapImpl(ptr, d.ptr, maxBuffered)             # <<<<<<<<<<<<<<
+ * 
+ * cdef class EventInputPort(Port):
+ */
+  MUSIC::Implementer::mapImpl(__pyx_v_ptr, __pyx_v_d->ptr, __pyx_v_maxBuffered);
+
+  /* "pymusic.pyx":184
+ *     Setup.publishContOutputPort(portname).
+ *     """
+ *     def map(self, object data,             # <<<<<<<<<<<<<<
+ *             int base=0, object perm=None,
+ *             int maxBuffered=-1):
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("pymusic.ContOutputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_buf);
+  __Pyx_XDECREF((PyObject *)__pyx_v_imap);
+  __Pyx_XDECREF((PyObject *)__pyx_v_d);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":217
+ *     here and drop the reference when this object is null'd (events member).
+ *     """
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Store a set of references to the event handlers
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_14EventInputPort_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_14EventInputPort_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) {
+    __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;}
+  if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__cinit__", 0))) return -1;
+  __pyx_r = __pyx_pf_7pymusic_14EventInputPort___cinit__(((struct __pyx_obj_7pymusic_EventInputPort *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_14EventInputPort___cinit__(struct __pyx_obj_7pymusic_EventInputPort *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":221
+ *         Store a set of references to the event handlers
+ *         """
+ *         self.events = set()             # <<<<<<<<<<<<<<
+ * 
+ *     cpdef null(self):
+ */
+  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->events);
+  __Pyx_DECREF(__pyx_v_self->events);
+  __pyx_v_self->events = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":217
+ *     here and drop the reference when this object is null'd (events member).
+ *     """
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Store a set of references to the event handlers
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.EventInputPort.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":223
+ *         self.events = set()
+ * 
+ *     cpdef null(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Not just null pointer, but give up the associated event
+ */
+
+static PyObject *__pyx_pw_7pymusic_14EventInputPort_3null(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_f_7pymusic_14EventInputPort_null(struct __pyx_obj_7pymusic_EventInputPort *__pyx_v_self, int __pyx_skip_dispatch) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("null", 0);
+  /* Check if called by wrapper */
+  if (unlikely(__pyx_skip_dispatch)) ;
+  /* Check if overridden in Python */
+  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
+    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_null); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_7pymusic_14EventInputPort_3null)) {
+      __Pyx_XDECREF(__pyx_r);
+      __Pyx_INCREF(__pyx_t_1);
+      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+      if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+        if (likely(__pyx_t_4)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_4);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_3, function);
+        }
+      }
+      if (__pyx_t_4) {
+        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      } else {
+        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      }
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_r = __pyx_t_2;
+      __pyx_t_2 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      goto __pyx_L0;
+    }
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  }
+
+  /* "pymusic.pyx":228
+ *         handlers.
+ *         """
+ *         Port.null(self)             # <<<<<<<<<<<<<<
+ *         self.events = None
+ * 
+ */
+  __pyx_t_1 = __pyx_f_7pymusic_4Port_null(((struct __pyx_obj_7pymusic_Port *)__pyx_v_self), 1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 228; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":229
+ *         """
+ *         Port.null(self)
+ *         self.events = None             # <<<<<<<<<<<<<<
+ * 
+ *     def map(self, func, IndexType t,
+ */
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->events);
+  __Pyx_DECREF(__pyx_v_self->events);
+  __pyx_v_self->events = ((PyObject*)Py_None);
+
+  /* "pymusic.pyx":223
+ *         self.events = set()
+ * 
+ *     cpdef null(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Not just null pointer, but give up the associated event
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("pymusic.EventInputPort.null", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_14EventInputPort_3null(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_7pymusic_14EventInputPort_2null[] = "\n        Not just null pointer, but give up the associated event\n        handlers.\n        ";
+static PyObject *__pyx_pw_7pymusic_14EventInputPort_3null(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("null (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_14EventInputPort_2null(((struct __pyx_obj_7pymusic_EventInputPort *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_14EventInputPort_2null(struct __pyx_obj_7pymusic_EventInputPort *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("null", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __pyx_f_7pymusic_14EventInputPort_null(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.EventInputPort.null", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":231
+ *         self.events = None
+ * 
+ *     def map(self, func, IndexType t,             # <<<<<<<<<<<<<<
+ *             double accLatency=0, int maxBuffered=-1,
+ *             object perm=None, int base=-1, int size=-1):
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_14EventInputPort_5map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7pymusic_14EventInputPort_4map[] = "\n        Map events to this sink.\n        func is:\n          void func(double value, IndexType GLOBAL|LOCAL, int index)\n        IndexType is (?) the index type to map the incoming sources\n            passed to the func (why, if we already know this?)\n        accLatency is the delivery delay relative to calculation time\n            (? is it ? What formula are we using here?)\n        maxBuffered is ticks to buffer\n        perm, base & size are passed to IndexMap\n        ";
+static PyObject *__pyx_pw_7pymusic_14EventInputPort_5map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_func = 0;
+  MUSIC::Index::Type __pyx_v_t;
+  double __pyx_v_accLatency;
+  int __pyx_v_maxBuffered;
+  PyObject *__pyx_v_perm = 0;
+  int __pyx_v_base;
+  int __pyx_v_size;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("map (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_func,&__pyx_n_s_t,&__pyx_n_s_accLatency,&__pyx_n_s_maxBuffered,&__pyx_n_s_perm,&__pyx_n_s_base,&__pyx_n_s_size,0};
+    PyObject* values[7] = {0,0,0,0,0,0,0};
+
+    /* "pymusic.pyx":233
+ *     def map(self, func, IndexType t,
+ *             double accLatency=0, int maxBuffered=-1,
+ *             object perm=None, int base=-1, int size=-1):             # <<<<<<<<<<<<<<
+ *         """
+ *         Map events to this sink.
+ */
+    values[4] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
+        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_func)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_t)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("map", 0, 2, 7, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 231; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_accLatency);
+          if (value) { values[2] = value; kw_args--; }
+        }
+        case  3:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_maxBuffered);
+          if (value) { values[3] = value; kw_args--; }
+        }
+        case  4:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_perm);
+          if (value) { values[4] = value; kw_args--; }
+        }
+        case  5:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_base);
+          if (value) { values[5] = value; kw_args--; }
+        }
+        case  6:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_size);
+          if (value) { values[6] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "map") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 231; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
+        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_func = values[0];
+    __pyx_v_t = ((MUSIC::Index::Type)PyInt_AsLong(values[1])); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 231; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    if (values[2]) {
+      __pyx_v_accLatency = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_accLatency == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_accLatency = ((double)0.0);
+    }
+    if (values[3]) {
+      __pyx_v_maxBuffered = __Pyx_PyInt_As_int(values[3]); if (unlikely((__pyx_v_maxBuffered == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_maxBuffered = ((int)-1);
+    }
+    __pyx_v_perm = values[4];
+    if (values[5]) {
+      __pyx_v_base = __Pyx_PyInt_As_int(values[5]); if (unlikely((__pyx_v_base == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_base = ((int)-1);
+    }
+    if (values[6]) {
+      __pyx_v_size = __Pyx_PyInt_As_int(values[6]); if (unlikely((__pyx_v_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_size = ((int)-1);
+    }
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("map", 0, 2, 7, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 231; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.EventInputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_14EventInputPort_4map(((struct __pyx_obj_7pymusic_EventInputPort *)__pyx_v_self), __pyx_v_func, __pyx_v_t, __pyx_v_accLatency, __pyx_v_maxBuffered, __pyx_v_perm, __pyx_v_base, __pyx_v_size);
+
+  /* "pymusic.pyx":231
+ *         self.events = None
+ * 
+ *     def map(self, func, IndexType t,             # <<<<<<<<<<<<<<
+ *             double accLatency=0, int maxBuffered=-1,
+ *             object perm=None, int base=-1, int size=-1):
+ */
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_14EventInputPort_4map(struct __pyx_obj_7pymusic_EventInputPort *__pyx_v_self, PyObject *__pyx_v_func, MUSIC::Index::Type __pyx_v_t, double __pyx_v_accLatency, int __pyx_v_maxBuffered, PyObject *__pyx_v_perm, int __pyx_v_base, int __pyx_v_size) {
+  struct __pyx_obj_7pymusic_IndexMap *__pyx_v_imap = 0;
+  struct __pyx_obj_7pymusic_EventHandler *__pyx_v_eh = 0;
+  MUSIC::EventInputPort *__pyx_v_ptr;
+  MUSIC::EventHandlerPtr __pyx_v_hndl;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_4;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("map", 0);
+
+  /* "pymusic.pyx":245
+ *         perm, base & size are passed to IndexMap
+ *         """
+ *         cdef IndexMap imap = IndexMap(perm, base, size)             # <<<<<<<<<<<<<<
+ *         cdef EventHandler eh = EventHandler(func, t)
+ *         cdef CEventInputPort* ptr = dc_CEventInputPort(self.ptr)
+ */
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_base); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_size); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_perm);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_perm);
+  __Pyx_GIVEREF(__pyx_v_perm);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_1 = 0;
+  __pyx_t_2 = 0;
+  __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_IndexMap)), __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_imap = ((struct __pyx_obj_7pymusic_IndexMap *)__pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":246
+ *         """
+ *         cdef IndexMap imap = IndexMap(perm, base, size)
+ *         cdef EventHandler eh = EventHandler(func, t)             # <<<<<<<<<<<<<<
+ *         cdef CEventInputPort* ptr = dc_CEventInputPort(self.ptr)
+ *         cdef CEventHandlerPtr hndl = getEventHandlerPtr(t, eh.ptr)
+ */
+  __pyx_t_2 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_func);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_func);
+  __Pyx_GIVEREF(__pyx_v_func);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_EventHandler)), __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_eh = ((struct __pyx_obj_7pymusic_EventHandler *)__pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":247
+ *         cdef IndexMap imap = IndexMap(perm, base, size)
+ *         cdef EventHandler eh = EventHandler(func, t)
+ *         cdef CEventInputPort* ptr = dc_CEventInputPort(self.ptr)             # <<<<<<<<<<<<<<
+ *         cdef CEventHandlerPtr hndl = getEventHandlerPtr(t, eh.ptr)
+ *         mapImpl(ptr, imap.ptr, t, hndl, accLatency, maxBuffered)
+ */
+  __pyx_v_ptr = dynamic_cast<MUSIC::EventInputPort*>(__pyx_v_self->__pyx_base.ptr);
+
+  /* "pymusic.pyx":248
+ *         cdef EventHandler eh = EventHandler(func, t)
+ *         cdef CEventInputPort* ptr = dc_CEventInputPort(self.ptr)
+ *         cdef CEventHandlerPtr hndl = getEventHandlerPtr(t, eh.ptr)             # <<<<<<<<<<<<<<
+ *         mapImpl(ptr, imap.ptr, t, hndl, accLatency, maxBuffered)
+ *         self.events.add(eh)
+ */
+  __pyx_v_hndl = MUSIC::getEventHandlerPtr(__pyx_v_t, __pyx_v_eh->ptr);
+
+  /* "pymusic.pyx":249
+ *         cdef CEventInputPort* ptr = dc_CEventInputPort(self.ptr)
+ *         cdef CEventHandlerPtr hndl = getEventHandlerPtr(t, eh.ptr)
+ *         mapImpl(ptr, imap.ptr, t, hndl, accLatency, maxBuffered)             # <<<<<<<<<<<<<<
+ *         self.events.add(eh)
+ * 
+ */
+  MUSIC::Implementer::mapImpl(__pyx_v_ptr, __pyx_v_imap->ptr, __pyx_v_t, __pyx_v_hndl, __pyx_v_accLatency, __pyx_v_maxBuffered);
+
+  /* "pymusic.pyx":250
+ *         cdef CEventHandlerPtr hndl = getEventHandlerPtr(t, eh.ptr)
+ *         mapImpl(ptr, imap.ptr, t, hndl, accLatency, maxBuffered)
+ *         self.events.add(eh)             # <<<<<<<<<<<<<<
+ * 
+ * cdef class EventOutputPort(Port):
+ */
+  if (unlikely(__pyx_v_self->events == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "add");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_4 = PySet_Add(__pyx_v_self->events, ((PyObject *)__pyx_v_eh)); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":231
+ *         self.events = None
+ * 
+ *     def map(self, func, IndexType t,             # <<<<<<<<<<<<<<
+ *             double accLatency=0, int maxBuffered=-1,
+ *             object perm=None, int base=-1, int size=-1):
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("pymusic.EventInputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_imap);
+  __Pyx_XDECREF((PyObject *)__pyx_v_eh);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":257
+ *     events.
+ *     """
+ *     def map(self, IndexType t, int maxBuffered=-1,             # <<<<<<<<<<<<<<
+ *             object perm=None, int base=-1, int size=-1):
+ *         """
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_15EventOutputPort_1map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7pymusic_15EventOutputPort_map[] = "\n        IndexType: LOCAL/GLOBAL\n        maxBuffered: tick to buffer (why on both sides?)\n        perm, base, size: define IndexMap (see that class)\n        ";
+static PyObject *__pyx_pw_7pymusic_15EventOutputPort_1map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  MUSIC::Index::Type __pyx_v_t;
+  int __pyx_v_maxBuffered;
+  PyObject *__pyx_v_perm = 0;
+  int __pyx_v_base;
+  int __pyx_v_size;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("map (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_t,&__pyx_n_s_maxBuffered,&__pyx_n_s_perm,&__pyx_n_s_base,&__pyx_n_s_size,0};
+    PyObject* values[5] = {0,0,0,0,0};
+
+    /* "pymusic.pyx":258
+ *     """
+ *     def map(self, IndexType t, int maxBuffered=-1,
+ *             object perm=None, int base=-1, int size=-1):             # <<<<<<<<<<<<<<
+ *         """
+ *         IndexType: LOCAL/GLOBAL
+ */
+    values[2] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_t)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_maxBuffered);
+          if (value) { values[1] = value; kw_args--; }
+        }
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_perm);
+          if (value) { values[2] = value; kw_args--; }
+        }
+        case  3:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_base);
+          if (value) { values[3] = value; kw_args--; }
+        }
+        case  4:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_size);
+          if (value) { values[4] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "map") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_t = ((MUSIC::Index::Type)PyInt_AsLong(values[0])); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    if (values[1]) {
+      __pyx_v_maxBuffered = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_maxBuffered == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_maxBuffered = ((int)-1);
+    }
+    __pyx_v_perm = values[2];
+    if (values[3]) {
+      __pyx_v_base = __Pyx_PyInt_As_int(values[3]); if (unlikely((__pyx_v_base == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_base = ((int)-1);
+    }
+    if (values[4]) {
+      __pyx_v_size = __Pyx_PyInt_As_int(values[4]); if (unlikely((__pyx_v_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_size = ((int)-1);
+    }
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("map", 0, 1, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.EventOutputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_15EventOutputPort_map(((struct __pyx_obj_7pymusic_EventOutputPort *)__pyx_v_self), __pyx_v_t, __pyx_v_maxBuffered, __pyx_v_perm, __pyx_v_base, __pyx_v_size);
+
+  /* "pymusic.pyx":257
+ *     events.
+ *     """
+ *     def map(self, IndexType t, int maxBuffered=-1,             # <<<<<<<<<<<<<<
+ *             object perm=None, int base=-1, int size=-1):
+ *         """
+ */
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_15EventOutputPort_map(struct __pyx_obj_7pymusic_EventOutputPort *__pyx_v_self, MUSIC::Index::Type __pyx_v_t, int __pyx_v_maxBuffered, PyObject *__pyx_v_perm, int __pyx_v_base, int __pyx_v_size) {
+  struct __pyx_obj_7pymusic_IndexMap *__pyx_v_m = 0;
+  MUSIC::EventOutputPort *__pyx_v_ptr;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("map", 0);
+
+  /* "pymusic.pyx":264
+ *         perm, base, size: define IndexMap (see that class)
+ *         """
+ *         cdef IndexMap m = IndexMap(perm, base, size)             # <<<<<<<<<<<<<<
+ *         cdef CEventOutputPort* ptr = dc_CEventOutputPort(self.ptr)
+ *         mapImpl(ptr, m.ptr, t, maxBuffered)
+ */
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_base); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_size); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_perm);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_perm);
+  __Pyx_GIVEREF(__pyx_v_perm);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_1 = 0;
+  __pyx_t_2 = 0;
+  __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_IndexMap)), __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_m = ((struct __pyx_obj_7pymusic_IndexMap *)__pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":265
+ *         """
+ *         cdef IndexMap m = IndexMap(perm, base, size)
+ *         cdef CEventOutputPort* ptr = dc_CEventOutputPort(self.ptr)             # <<<<<<<<<<<<<<
+ *         mapImpl(ptr, m.ptr, t, maxBuffered)
+ * 
+ */
+  __pyx_v_ptr = dynamic_cast<MUSIC::EventOutputPort*>(__pyx_v_self->__pyx_base.ptr);
+
+  /* "pymusic.pyx":266
+ *         cdef IndexMap m = IndexMap(perm, base, size)
+ *         cdef CEventOutputPort* ptr = dc_CEventOutputPort(self.ptr)
+ *         mapImpl(ptr, m.ptr, t, maxBuffered)             # <<<<<<<<<<<<<<
+ * 
+ *     def insertEvent(self, double time, int index, IndexType t):
+ */
+  MUSIC::Implementer::mapImpl(__pyx_v_ptr, __pyx_v_m->ptr, __pyx_v_t, __pyx_v_maxBuffered);
+
+  /* "pymusic.pyx":257
+ *     events.
+ *     """
+ *     def map(self, IndexType t, int maxBuffered=-1,             # <<<<<<<<<<<<<<
+ *             object perm=None, int base=-1, int size=-1):
+ *         """
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("pymusic.EventOutputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_m);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":268
+ *         mapImpl(ptr, m.ptr, t, maxBuffered)
+ * 
+ *     def insertEvent(self, double time, int index, IndexType t):             # <<<<<<<<<<<<<<
+ *         """
+ *         double time: time of event (must be during current tick)
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_15EventOutputPort_3insertEvent(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7pymusic_15EventOutputPort_2insertEvent[] = "\n        double time: time of event (must be during current tick)\n        int index: local or global index of event\n        IndexType t: LOCAL|GLOBAL\n        ";
+static PyObject *__pyx_pw_7pymusic_15EventOutputPort_3insertEvent(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  double __pyx_v_time;
+  int __pyx_v_index;
+  CYTHON_UNUSED MUSIC::Index::Type __pyx_v_t;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("insertEvent (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_time,&__pyx_n_s_index,&__pyx_n_s_t,0};
+    PyObject* values[3] = {0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_time)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_index)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("insertEvent", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+        case  2:
+        if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_t)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("insertEvent", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "insertEvent") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+    }
+    __pyx_v_time = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_time == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_index = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_index == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_t = ((MUSIC::Index::Type)PyInt_AsLong(values[2])); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("insertEvent", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.EventOutputPort.insertEvent", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_15EventOutputPort_2insertEvent(((struct __pyx_obj_7pymusic_EventOutputPort *)__pyx_v_self), __pyx_v_time, __pyx_v_index, __pyx_v_t);
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_15EventOutputPort_2insertEvent(struct __pyx_obj_7pymusic_EventOutputPort *__pyx_v_self, double __pyx_v_time, int __pyx_v_index, CYTHON_UNUSED MUSIC::Index::Type __pyx_v_t) {
+  MUSIC::EventOutputPort *__pyx_v_ptr;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("insertEvent", 0);
+
+  /* "pymusic.pyx":274
+ *         IndexType t: LOCAL|GLOBAL
+ *         """
+ *         cdef CEventOutputPort* ptr = dc_CEventOutputPort(self.ptr)             # <<<<<<<<<<<<<<
+ *         insertEventImpl(ptr, time, index)
+ * 
+ */
+  __pyx_v_ptr = dynamic_cast<MUSIC::EventOutputPort*>(__pyx_v_self->__pyx_base.ptr);
+
+  /* "pymusic.pyx":275
+ *         """
+ *         cdef CEventOutputPort* ptr = dc_CEventOutputPort(self.ptr)
+ *         insertEventImpl(ptr, time, index)             # <<<<<<<<<<<<<<
+ * 
+ * cdef class MessageInputPort(Port):
+ */
+  MUSIC::Implementer::insertEventImpl(__pyx_v_ptr, __pyx_v_time, __pyx_v_index);
+
+  /* "pymusic.pyx":268
+ *         mapImpl(ptr, m.ptr, t, maxBuffered)
+ * 
+ *     def insertEvent(self, double time, int index, IndexType t):             # <<<<<<<<<<<<<<
+ *         """
+ *         double time: time of event (must be during current tick)
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":285
+ *     here and drop the reference when this object is null'd.
+ *     """
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         self.events = set()
+ * 
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_16MessageInputPort_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_16MessageInputPort_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) {
+    __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;}
+  if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__cinit__", 0))) return -1;
+  __pyx_r = __pyx_pf_7pymusic_16MessageInputPort___cinit__(((struct __pyx_obj_7pymusic_MessageInputPort *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_16MessageInputPort___cinit__(struct __pyx_obj_7pymusic_MessageInputPort *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":286
+ *     """
+ *     def __cinit__(self):
+ *         self.events = set()             # <<<<<<<<<<<<<<
+ * 
+ *     cpdef null(self):
+ */
+  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 286; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->events);
+  __Pyx_DECREF(__pyx_v_self->events);
+  __pyx_v_self->events = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":285
+ *     here and drop the reference when this object is null'd.
+ *     """
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         self.events = set()
+ * 
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.MessageInputPort.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":288
+ *         self.events = set()
+ * 
+ *     cpdef null(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Remember to remove the references to events...
+ */
+
+static PyObject *__pyx_pw_7pymusic_16MessageInputPort_3null(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_f_7pymusic_16MessageInputPort_null(struct __pyx_obj_7pymusic_MessageInputPort *__pyx_v_self, int __pyx_skip_dispatch) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("null", 0);
+  /* Check if called by wrapper */
+  if (unlikely(__pyx_skip_dispatch)) ;
+  /* Check if overridden in Python */
+  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
+    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_null); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_7pymusic_16MessageInputPort_3null)) {
+      __Pyx_XDECREF(__pyx_r);
+      __Pyx_INCREF(__pyx_t_1);
+      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+      if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+        if (likely(__pyx_t_4)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_4);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_3, function);
+        }
+      }
+      if (__pyx_t_4) {
+        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      } else {
+        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      }
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_r = __pyx_t_2;
+      __pyx_t_2 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      goto __pyx_L0;
+    }
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  }
+
+  /* "pymusic.pyx":292
+ *         Remember to remove the references to events...
+ *         """
+ *         Port.null(self)             # <<<<<<<<<<<<<<
+ *         self.events = None
+ * 
+ */
+  __pyx_t_1 = __pyx_f_7pymusic_4Port_null(((struct __pyx_obj_7pymusic_Port *)__pyx_v_self), 1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 292; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":293
+ *         """
+ *         Port.null(self)
+ *         self.events = None             # <<<<<<<<<<<<<<
+ * 
+ *     def map(self, func, double accLatency=0, int maxBuffered=-1, bint pickled=True):
+ */
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->events);
+  __Pyx_DECREF(__pyx_v_self->events);
+  __pyx_v_self->events = ((PyObject*)Py_None);
+
+  /* "pymusic.pyx":288
+ *         self.events = set()
+ * 
+ *     cpdef null(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Remember to remove the references to events...
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("pymusic.MessageInputPort.null", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_16MessageInputPort_3null(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_7pymusic_16MessageInputPort_2null[] = "\n        Remember to remove the references to events...\n        ";
+static PyObject *__pyx_pw_7pymusic_16MessageInputPort_3null(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("null (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_16MessageInputPort_2null(((struct __pyx_obj_7pymusic_MessageInputPort *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_16MessageInputPort_2null(struct __pyx_obj_7pymusic_MessageInputPort *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("null", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __pyx_f_7pymusic_16MessageInputPort_null(__pyx_v_self, 1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.MessageInputPort.null", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":295
+ *         self.events = None
+ * 
+ *     def map(self, func, double accLatency=0, int maxBuffered=-1, bint pickled=True):             # <<<<<<<<<<<<<<
+ *         """
+ *         The message handling function.
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_16MessageInputPort_5map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7pymusic_16MessageInputPort_4map[] = "\n        The message handling function.\n        func: callable object as follows\n           void func(double time, object msg):\n             time: the set insertion time of the message\n             msg: an object which may have been pickled and fed through music\n        accLatency(0): \"acceptable latency\" (\077\077?)\n        maxBuffered(-1): ticks that can be buffered (-1 means unknown\n           amount (\077\077?))\n        pickled(True): pickle objects on both ends; else, the object should be\n                       a buffer object and we'll receive a bytearray\n        ";
+static PyObject *__pyx_pw_7pymusic_16MessageInputPort_5map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_func = 0;
+  double __pyx_v_accLatency;
+  int __pyx_v_maxBuffered;
+  int __pyx_v_pickled;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("map (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_func,&__pyx_n_s_accLatency,&__pyx_n_s_maxBuffered,&__pyx_n_s_pickled,0};
+    PyObject* values[4] = {0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_func)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_accLatency);
+          if (value) { values[1] = value; kw_args--; }
+        }
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_maxBuffered);
+          if (value) { values[2] = value; kw_args--; }
+        }
+        case  3:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_pickled);
+          if (value) { values[3] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "map") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_func = values[0];
+    if (values[1]) {
+      __pyx_v_accLatency = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_accLatency == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_accLatency = ((double)0.0);
+    }
+    if (values[2]) {
+      __pyx_v_maxBuffered = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_maxBuffered == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_maxBuffered = ((int)-1);
+    }
+    if (values[3]) {
+      __pyx_v_pickled = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_pickled == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_pickled = ((int)1);
+    }
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("map", 0, 1, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.MessageInputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_16MessageInputPort_4map(((struct __pyx_obj_7pymusic_MessageInputPort *)__pyx_v_self), __pyx_v_func, __pyx_v_accLatency, __pyx_v_maxBuffered, __pyx_v_pickled);
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_16MessageInputPort_4map(struct __pyx_obj_7pymusic_MessageInputPort *__pyx_v_self, PyObject *__pyx_v_func, double __pyx_v_accLatency, int __pyx_v_maxBuffered, int __pyx_v_pickled) {
+  struct __pyx_obj_7pymusic_MessageHandler *__pyx_v_eh = 0;
+  MUSIC::MessageInputPort *__pyx_v_ptr;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_t_3;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("map", 0);
+
+  /* "pymusic.pyx":308
+ *                        a buffer object and we'll receive a bytearray
+ *         """
+ *         cdef MessageHandler eh = MessageHandler(func, pickled)             # <<<<<<<<<<<<<<
+ *         cdef CMessageInputPort* ptr = dc_CMessageInputPort(self.ptr)
+ *         mapImpl(ptr, eh.ptr, accLatency, maxBuffered)
+ */
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_pickled); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 308; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 308; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(__pyx_v_func);
+  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_func);
+  __Pyx_GIVEREF(__pyx_v_func);
+  PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_MessageHandler)), __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 308; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_v_eh = ((struct __pyx_obj_7pymusic_MessageHandler *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":309
+ *         """
+ *         cdef MessageHandler eh = MessageHandler(func, pickled)
+ *         cdef CMessageInputPort* ptr = dc_CMessageInputPort(self.ptr)             # <<<<<<<<<<<<<<
+ *         mapImpl(ptr, eh.ptr, accLatency, maxBuffered)
+ *         self.events.add(eh)
+ */
+  __pyx_v_ptr = dynamic_cast<MUSIC::MessageInputPort*>(__pyx_v_self->__pyx_base.ptr);
+
+  /* "pymusic.pyx":310
+ *         cdef MessageHandler eh = MessageHandler(func, pickled)
+ *         cdef CMessageInputPort* ptr = dc_CMessageInputPort(self.ptr)
+ *         mapImpl(ptr, eh.ptr, accLatency, maxBuffered)             # <<<<<<<<<<<<<<
+ *         self.events.add(eh)
+ * 
+ */
+  MUSIC::Implementer::mapImpl(__pyx_v_ptr, __pyx_v_eh->ptr, __pyx_v_accLatency, __pyx_v_maxBuffered);
+
+  /* "pymusic.pyx":311
+ *         cdef CMessageInputPort* ptr = dc_CMessageInputPort(self.ptr)
+ *         mapImpl(ptr, eh.ptr, accLatency, maxBuffered)
+ *         self.events.add(eh)             # <<<<<<<<<<<<<<
+ * 
+ * cdef class MessageOutputPort(Port):
+ */
+  if (unlikely(__pyx_v_self->events == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "add");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_3 = PySet_Add(__pyx_v_self->events, ((PyObject *)__pyx_v_eh)); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":295
+ *         self.events = None
+ * 
+ *     def map(self, func, double accLatency=0, int maxBuffered=-1, bint pickled=True):             # <<<<<<<<<<<<<<
+ *         """
+ *         The message handling function.
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("pymusic.MessageInputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_eh);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":318
+ *     pickled and fed to the other end, associated with a time.
+ *     """
+ *     def map(self, int maxBuffered=-1, bint pickled=True):             # <<<<<<<<<<<<<<
+ *         """
+ *         map only sets the buffering ticks.
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_17MessageOutputPort_1map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7pymusic_17MessageOutputPort_map[] = "\n        map only sets the buffering ticks.\n        maxBuffered (-1): ticks to buffer (-1 means \"reasonable\" \077\077?)\n        pickled (True): whether messages objects inserted her are automatically\n                        pickled, else the object should be a buffer-type and\n                        the other end will get a bytearray.\n        ";
+static PyObject *__pyx_pw_7pymusic_17MessageOutputPort_1map(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  int __pyx_v_maxBuffered;
+  int __pyx_v_pickled;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("map (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_maxBuffered,&__pyx_n_s_pickled,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_maxBuffered);
+          if (value) { values[0] = value; kw_args--; }
+        }
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_pickled);
+          if (value) { values[1] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "map") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    if (values[0]) {
+      __pyx_v_maxBuffered = __Pyx_PyInt_As_int(values[0]); if (unlikely((__pyx_v_maxBuffered == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_maxBuffered = ((int)-1);
+    }
+    if (values[1]) {
+      __pyx_v_pickled = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_pickled == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_pickled = ((int)1);
+    }
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("map", 0, 0, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.MessageOutputPort.map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_17MessageOutputPort_map(((struct __pyx_obj_7pymusic_MessageOutputPort *)__pyx_v_self), __pyx_v_maxBuffered, __pyx_v_pickled);
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_17MessageOutputPort_map(struct __pyx_obj_7pymusic_MessageOutputPort *__pyx_v_self, int __pyx_v_maxBuffered, int __pyx_v_pickled) {
+  MUSIC::MessageOutputPort *__pyx_v_ptr;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("map", 0);
+
+  /* "pymusic.pyx":326
+ *                         the other end will get a bytearray.
+ *         """
+ *         self.pickled = pickled             # <<<<<<<<<<<<<<
+ *         cdef CMessageOutputPort* ptr = dc_CMessageOutputPort(self.ptr)
+ *         mapImpl(ptr, maxBuffered)
+ */
+  __pyx_v_self->pickled = __pyx_v_pickled;
+
+  /* "pymusic.pyx":327
+ *         """
+ *         self.pickled = pickled
+ *         cdef CMessageOutputPort* ptr = dc_CMessageOutputPort(self.ptr)             # <<<<<<<<<<<<<<
+ *         mapImpl(ptr, maxBuffered)
+ * 
+ */
+  __pyx_v_ptr = dynamic_cast<MUSIC::MessageOutputPort*>(__pyx_v_self->__pyx_base.ptr);
+
+  /* "pymusic.pyx":328
+ *         self.pickled = pickled
+ *         cdef CMessageOutputPort* ptr = dc_CMessageOutputPort(self.ptr)
+ *         mapImpl(ptr, maxBuffered)             # <<<<<<<<<<<<<<
+ * 
+ *     def insertMessage(self, double time, object msg):
+ */
+  MUSIC::Implementer::mapImpl(__pyx_v_ptr, __pyx_v_maxBuffered);
+
+  /* "pymusic.pyx":318
+ *     pickled and fed to the other end, associated with a time.
+ *     """
+ *     def map(self, int maxBuffered=-1, bint pickled=True):             # <<<<<<<<<<<<<<
+ *         """
+ *         map only sets the buffering ticks.
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":330
+ *         mapImpl(ptr, maxBuffered)
+ * 
+ *     def insertMessage(self, double time, object msg):             # <<<<<<<<<<<<<<
+ *         """
+ *         insert a python object as a message at a time during the
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_17MessageOutputPort_3insertMessage(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_7pymusic_17MessageOutputPort_2insertMessage[] = "\n        insert a python object as a message at a time during the\n        current tick.\n        time: ms times (\077\077)\n        msg: a python object that can be cPickled if self.pickled == True\n             else something that has a buffer interface.\n        ";
+static PyObject *__pyx_pw_7pymusic_17MessageOutputPort_3insertMessage(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  double __pyx_v_time;
+  PyObject *__pyx_v_msg = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("insertMessage (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_time,&__pyx_n_s_msg,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_time)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_msg)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("insertMessage", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "insertMessage") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_time = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_time == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_msg = values[1];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("insertMessage", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.MessageOutputPort.insertMessage", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_17MessageOutputPort_2insertMessage(((struct __pyx_obj_7pymusic_MessageOutputPort *)__pyx_v_self), __pyx_v_time, __pyx_v_msg);
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_17MessageOutputPort_2insertMessage(struct __pyx_obj_7pymusic_MessageOutputPort *__pyx_v_self, double __pyx_v_time, PyObject *__pyx_v_msg) {
+  MUSIC::MessageOutputPort *__pyx_v_ptr;
+  PyObject *__pyx_v_pmsg = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  Py_ssize_t __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
+  char *__pyx_t_8;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("insertMessage", 0);
+
+  /* "pymusic.pyx":338
+ *              else something that has a buffer interface.
+ *         """
+ *         cdef CMessageOutputPort* ptr = dc_CMessageOutputPort(self.ptr)             # <<<<<<<<<<<<<<
+ *         cdef bytearray pmsg =                                           \
+ *                 <bytearray> pickle.dumps(msg, pickle.HIGHEST_PROTOCOL)  \
+ */
+  __pyx_v_ptr = dynamic_cast<MUSIC::MessageOutputPort*>(__pyx_v_self->__pyx_base.ptr);
+
+  /* "pymusic.pyx":341
+ *         cdef bytearray pmsg =                                           \
+ *                 <bytearray> pickle.dumps(msg, pickle.HIGHEST_PROTOCOL)  \
+ *                 if self.pickled                                         \             # <<<<<<<<<<<<<<
+ *                 else <bytearray> msg
+ *         ptr.insertMessage(time, <char*> pmsg, len(pmsg))
+ */
+  if ((__pyx_v_self->pickled != 0)) {
+
+    /* "pymusic.pyx":340
+ *         cdef CMessageOutputPort* ptr = dc_CMessageOutputPort(self.ptr)
+ *         cdef bytearray pmsg =                                           \
+ *                 <bytearray> pickle.dumps(msg, pickle.HIGHEST_PROTOCOL)  \             # <<<<<<<<<<<<<<
+ *                 if self.pickled                                         \
+ *                 else <bytearray> msg
+ */
+    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_pickle); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_dumps); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_pickle); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_HIGHEST_PROTOCOL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_3 = NULL;
+    __pyx_t_6 = 0;
+    if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_3)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+        __pyx_t_6 = 1;
+      }
+    }
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_7);
+    if (__pyx_t_3) {
+      PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3); __Pyx_GIVEREF(__pyx_t_3); __pyx_t_3 = NULL;
+    }
+    __Pyx_INCREF(__pyx_v_msg);
+    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_v_msg);
+    __Pyx_GIVEREF(__pyx_v_msg);
+    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_5);
+    __pyx_t_5 = 0;
+    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_7, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 340; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_INCREF(((PyObject*)__pyx_t_2));
+    __pyx_t_1 = __pyx_t_2;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  } else {
+
+    /* "pymusic.pyx":342
+ *                 <bytearray> pickle.dumps(msg, pickle.HIGHEST_PROTOCOL)  \
+ *                 if self.pickled                                         \
+ *                 else <bytearray> msg             # <<<<<<<<<<<<<<
+ *         ptr.insertMessage(time, <char*> pmsg, len(pmsg))
+ * 
+ */
+    __Pyx_INCREF(((PyObject*)__pyx_v_msg));
+    __pyx_t_1 = __pyx_v_msg;
+  }
+  __pyx_v_pmsg = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":343
+ *                 if self.pickled                                         \
+ *                 else <bytearray> msg
+ *         ptr.insertMessage(time, <char*> pmsg, len(pmsg))             # <<<<<<<<<<<<<<
+ * 
+ * ###########################################################
+ */
+  __pyx_t_8 = __Pyx_PyObject_AsString(__pyx_v_pmsg); if (unlikely((!__pyx_t_8) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = PyObject_Length(__pyx_v_pmsg); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_ptr->insertMessage(__pyx_v_time, ((char *)__pyx_t_8), __pyx_t_6);
+
+  /* "pymusic.pyx":330
+ *         mapImpl(ptr, maxBuffered)
+ * 
+ *     def insertMessage(self, double time, object msg):             # <<<<<<<<<<<<<<
+ *         """
+ *         insert a python object as a message at a time during the
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("pymusic.MessageOutputPort.insertMessage", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_pmsg);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":357
+ *     """
+ * 
+ *     def __cinit__(self, list argv=None, required=None):             # <<<<<<<<<<<<<<
+ *         """
+ *         Takes the command line arguments and the required threading
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_5Setup_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_5Setup_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_argv = 0;
+  PyObject *__pyx_v_required = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_argv,&__pyx_n_s_required,0};
+    PyObject* values[2] = {0,0};
+    values[0] = ((PyObject*)Py_None);
+    values[1] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_argv);
+          if (value) { values[0] = value; kw_args--; }
+        }
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_required);
+          if (value) { values[1] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 357; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_argv = ((PyObject*)values[0]);
+    __pyx_v_required = values[1];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 357; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Setup.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_argv), (&PyList_Type), 1, "argv", 1))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 357; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_7pymusic_5Setup___cinit__(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self), __pyx_v_argv, __pyx_v_required);
+
+  /* function exit code */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_5Setup___cinit__(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, PyObject *__pyx_v_argv, PyObject *__pyx_v_required) {
+  int __pyx_v_provided;
+  __pyx_t_7pymusic_Args __pyx_v_r;
+  struct PyMPIIntracommObject *__pyx_v_comm = 0;
+  int __pyx_v_i;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_t_5;
+  MUSIC::Setup *__pyx_t_6;
+  int __pyx_t_7;
+  int __pyx_t_8;
+  char const *__pyx_t_9;
+  PyObject *__pyx_t_10 = NULL;
+  PyObject *__pyx_t_11 = NULL;
+  PyObject *__pyx_t_12 = NULL;
+  PyObject *__pyx_t_13 = NULL;
+  PyObject *__pyx_t_14 = NULL;
+  PyObject *__pyx_t_15 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":372
+ *         cdef int provided
+ * 
+ *         cdef Args r = argv_toc(argv if argv is not None             # <<<<<<<<<<<<<<
+ *                                else sys.argv)
+ *         try:
+ */
+  __pyx_t_2 = (__pyx_v_argv != ((PyObject*)Py_None));
+  if ((__pyx_t_2 != 0)) {
+    __Pyx_INCREF(__pyx_v_argv);
+    __pyx_t_1 = __pyx_v_argv;
+  } else {
+
+    /* "pymusic.pyx":373
+ * 
+ *         cdef Args r = argv_toc(argv if argv is not None
+ *                                else sys.argv)             # <<<<<<<<<<<<<<
+ *         try:
+ *             if required is None:
+ */
+    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_sys); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_argv); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (!(likely(PyList_CheckExact(__pyx_t_4))||((__pyx_t_4) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "list", Py_TYPE(__pyx_t_4)->tp_name), 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 373; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __pyx_t_4;
+    __pyx_t_4 = 0;
+  }
+
+  /* "pymusic.pyx":372
+ *         cdef int provided
+ * 
+ *         cdef Args r = argv_toc(argv if argv is not None             # <<<<<<<<<<<<<<
+ *                                else sys.argv)
+ *         try:
+ */
+  __pyx_v_r = __pyx_f_7pymusic_argv_toc(((PyObject*)__pyx_t_1));
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":374
+ *         cdef Args r = argv_toc(argv if argv is not None
+ *                                else sys.argv)
+ *         try:             # <<<<<<<<<<<<<<
+ *             if required is None:
+ *                 self.ptr = new CSetup(r.argc, r.argv)
+ */
+  /*try:*/ {
+
+    /* "pymusic.pyx":375
+ *                                else sys.argv)
+ *         try:
+ *             if required is None:             # <<<<<<<<<<<<<<
+ *                 self.ptr = new CSetup(r.argc, r.argv)
+ *                 self.provided = MPI_THREAD_SINGLE
+ */
+    __pyx_t_2 = (__pyx_v_required == Py_None);
+    __pyx_t_5 = (__pyx_t_2 != 0);
+    if (__pyx_t_5) {
+
+      /* "pymusic.pyx":376
+ *         try:
+ *             if required is None:
+ *                 self.ptr = new CSetup(r.argc, r.argv)             # <<<<<<<<<<<<<<
+ *                 self.provided = MPI_THREAD_SINGLE
+ *             else:
+ */
+      try {
+        __pyx_t_6 = new MUSIC::Setup(__pyx_v_r.argc, __pyx_v_r.argv);
+      } catch(...) {
+        __Pyx_CppExn2PyErr();
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 376; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+      }
+      __pyx_v_self->ptr = __pyx_t_6;
+
+      /* "pymusic.pyx":377
+ *             if required is None:
+ *                 self.ptr = new CSetup(r.argc, r.argv)
+ *                 self.provided = MPI_THREAD_SINGLE             # <<<<<<<<<<<<<<
+ *             else:
+ *                 self.ptr = new CSetup(r.argc, r.argv, required, &provided)
+ */
+      __pyx_v_self->provided = MPI_THREAD_SINGLE;
+      goto __pyx_L6;
+    }
+    /*else*/ {
+
+      /* "pymusic.pyx":379
+ *                 self.provided = MPI_THREAD_SINGLE
+ *             else:
+ *                 self.ptr = new CSetup(r.argc, r.argv, required, &provided)             # <<<<<<<<<<<<<<
+ *                 self.provided = provided
+ *             self.argv = [r.argv[i] for i in xrange(r.argc)]
+ */
+      __pyx_t_7 = __Pyx_PyInt_As_int(__pyx_v_required); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 379; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+      try {
+        __pyx_t_6 = new MUSIC::Setup(__pyx_v_r.argc, __pyx_v_r.argv, __pyx_t_7, (&__pyx_v_provided));
+      } catch(...) {
+        __Pyx_CppExn2PyErr();
+        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 379; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+      }
+      __pyx_v_self->ptr = __pyx_t_6;
+
+      /* "pymusic.pyx":380
+ *             else:
+ *                 self.ptr = new CSetup(r.argc, r.argv, required, &provided)
+ *                 self.provided = provided             # <<<<<<<<<<<<<<
+ *             self.argv = [r.argv[i] for i in xrange(r.argc)]
+ *         finally:
+ */
+      __pyx_v_self->provided = __pyx_v_provided;
+    }
+    __pyx_L6:;
+
+    /* "pymusic.pyx":381
+ *                 self.ptr = new CSetup(r.argc, r.argv, required, &provided)
+ *                 self.provided = provided
+ *             self.argv = [r.argv[i] for i in xrange(r.argc)]             # <<<<<<<<<<<<<<
+ *         finally:
+ *             free(r.argv)
+ */
+    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_7 = __pyx_v_r.argc;
+    for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) {
+      __pyx_v_i = __pyx_t_8;
+      __pyx_t_4 = __Pyx_PyBytes_FromString((__pyx_v_r.argv[__pyx_v_i])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_4))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    }
+    __Pyx_GIVEREF(__pyx_t_1);
+    __Pyx_GOTREF(__pyx_v_self->argv);
+    __Pyx_DECREF(__pyx_v_self->argv);
+    __pyx_v_self->argv = ((PyObject*)__pyx_t_1);
+    __pyx_t_1 = 0;
+  }
+
+  /* "pymusic.pyx":383
+ *             self.argv = [r.argv[i] for i in xrange(r.argc)]
+ *         finally:
+ *             free(r.argv)             # <<<<<<<<<<<<<<
+ * 
+ *         cdef MPI.Intracomm comm = MPI.Intracomm()
+ */
+  /*finally:*/ {
+    /*normal exit:*/{
+      free(__pyx_v_r.argv);
+      goto __pyx_L5;
+    }
+    /*exception exit:*/{
+      __pyx_L4_error:;
+      __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
+      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+      if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15);
+      if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12) < 0)) __Pyx_ErrFetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
+      __Pyx_XGOTREF(__pyx_t_10);
+      __Pyx_XGOTREF(__pyx_t_11);
+      __Pyx_XGOTREF(__pyx_t_12);
+      __Pyx_XGOTREF(__pyx_t_13);
+      __Pyx_XGOTREF(__pyx_t_14);
+      __Pyx_XGOTREF(__pyx_t_15);
+      __pyx_t_7 = __pyx_lineno; __pyx_t_8 = __pyx_clineno; __pyx_t_9 = __pyx_filename;
+      {
+        free(__pyx_v_r.argv);
+      }
+      if (PY_MAJOR_VERSION >= 3) {
+        __Pyx_XGIVEREF(__pyx_t_13);
+        __Pyx_XGIVEREF(__pyx_t_14);
+        __Pyx_XGIVEREF(__pyx_t_15);
+        __Pyx_ExceptionReset(__pyx_t_13, __pyx_t_14, __pyx_t_15);
+      }
+      __Pyx_XGIVEREF(__pyx_t_10);
+      __Pyx_XGIVEREF(__pyx_t_11);
+      __Pyx_XGIVEREF(__pyx_t_12);
+      __Pyx_ErrRestore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
+      __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
+      __pyx_lineno = __pyx_t_7; __pyx_clineno = __pyx_t_8; __pyx_filename = __pyx_t_9;
+      goto __pyx_L1_error;
+    }
+    __pyx_L5:;
+  }
+
+  /* "pymusic.pyx":385
+ *             free(r.argv)
+ * 
+ *         cdef MPI.Intracomm comm = MPI.Intracomm()             # <<<<<<<<<<<<<<
+ *         comm.ob_mpi = communicator(self.ptr)
+ *         self.comm = comm
+ */
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_6mpi4py_3MPI_Intracomm)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_comm = ((struct PyMPIIntracommObject *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":386
+ * 
+ *         cdef MPI.Intracomm comm = MPI.Intracomm()
+ *         comm.ob_mpi = communicator(self.ptr)             # <<<<<<<<<<<<<<
+ *         self.comm = comm
+ * 
+ */
+  __pyx_v_comm->__pyx_base.ob_mpi = MUSIC::communicator(__pyx_v_self->ptr);
+
+  /* "pymusic.pyx":387
+ *         cdef MPI.Intracomm comm = MPI.Intracomm()
+ *         comm.ob_mpi = communicator(self.ptr)
+ *         self.comm = comm             # <<<<<<<<<<<<<<
+ * 
+ *         self.ports = set()
+ */
+  __Pyx_INCREF(((PyObject *)__pyx_v_comm));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_comm));
+  __Pyx_GOTREF(__pyx_v_self->comm);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->comm));
+  __pyx_v_self->comm = __pyx_v_comm;
+
+  /* "pymusic.pyx":389
+ *         self.comm = comm
+ * 
+ *         self.ports = set()             # <<<<<<<<<<<<<<
+ * 
+ *     def __dealloc__(self):
+ */
+  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 389; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->ports);
+  __Pyx_DECREF(__pyx_v_self->ports);
+  __pyx_v_self->ports = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":357
+ *     """
+ * 
+ *     def __cinit__(self, list argv=None, required=None):             # <<<<<<<<<<<<<<
+ *         """
+ *         Takes the command line arguments and the required threading
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("pymusic.Setup.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_comm);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":391
+ *         self.ports = set()
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         If runtime has been made and setup is invalid, do nothing.
+ */
+
+/* Python wrapper */
+static void __pyx_pw_7pymusic_5Setup_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_7pymusic_5Setup_3__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_7pymusic_5Setup_2__dealloc__(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+static void __pyx_pf_7pymusic_5Setup_2__dealloc__(struct __pyx_obj_7pymusic_Setup *__pyx_v_self) {
+  PyObject *__pyx_v_p = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *(*__pyx_t_3)(PyObject *);
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
+
+  /* "pymusic.pyx":397
+ *         """
+ * 
+ *         if self.ptr is NULL:             # <<<<<<<<<<<<<<
+ *             return
+ * 
+ */
+  __pyx_t_1 = ((__pyx_v_self->ptr == NULL) != 0);
+  if (__pyx_t_1) {
+
+    /* "pymusic.pyx":398
+ * 
+ *         if self.ptr is NULL:
+ *             return             # <<<<<<<<<<<<<<
+ * 
+ *         del self.ptr
+ */
+    goto __pyx_L0;
+  }
+
+  /* "pymusic.pyx":400
+ *             return
+ * 
+ *         del self.ptr             # <<<<<<<<<<<<<<
+ *         for p in self.ports:
+ *             del p.ptr
+ */
+  delete __pyx_v_self->ptr;
+
+  /* "pymusic.pyx":401
+ * 
+ *         del self.ptr
+ *         for p in self.ports:             # <<<<<<<<<<<<<<
+ *             del p.ptr
+ *             p.null()
+ */
+  __pyx_t_2 = PyObject_GetIter(__pyx_v_self->ports); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 401; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 401; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  for (;;) {
+    {
+      __pyx_t_4 = __pyx_t_3(__pyx_t_2);
+      if (unlikely(!__pyx_t_4)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 401; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_4);
+    }
+    __Pyx_XDECREF_SET(__pyx_v_p, __pyx_t_4);
+    __pyx_t_4 = 0;
+
+    /* "pymusic.pyx":402
+ *         del self.ptr
+ *         for p in self.ports:
+ *             del p.ptr             # <<<<<<<<<<<<<<
+ *             p.null()
+ *         self.null()
+ */
+    if (__Pyx_PyObject_DelAttrStr(__pyx_v_p, __pyx_n_s_ptr) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 402; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+    /* "pymusic.pyx":403
+ *         for p in self.ports:
+ *             del p.ptr
+ *             p.null()             # <<<<<<<<<<<<<<
+ *         self.null()
+ * 
+ */
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_p, __pyx_n_s_null); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 403; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(__pyx_t_5))) {
+      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+      if (likely(__pyx_t_6)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_6);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_5, function);
+      }
+    }
+    if (__pyx_t_6) {
+      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 403; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    } else {
+      __pyx_t_4 = __Pyx_PyObject_CallNoArg(__pyx_t_5); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 403; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+
+    /* "pymusic.pyx":401
+ * 
+ *         del self.ptr
+ *         for p in self.ports:             # <<<<<<<<<<<<<<
+ *             del p.ptr
+ *             p.null()
+ */
+  }
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":404
+ *             del p.ptr
+ *             p.null()
+ *         self.null()             # <<<<<<<<<<<<<<
+ * 
+ *     cpdef MPI.Intracomm getcomm(self):
+ */
+  __pyx_t_2 = ((struct __pyx_vtabstruct_7pymusic_Setup *)__pyx_v_self->__pyx_vtab)->null(__pyx_v_self); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":391
+ *         self.ports = set()
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         If runtime has been made and setup is invalid, do nothing.
+ */
+
+  /* function exit code */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_WriteUnraisable("pymusic.Setup.__dealloc__", __pyx_clineno, __pyx_lineno, __pyx_filename, 0);
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_p);
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "pymusic.pyx":406
+ *         self.null()
+ * 
+ *     cpdef MPI.Intracomm getcomm(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Get an MPI communicator between the processes on this current
+ */
+
+static PyObject *__pyx_pw_7pymusic_5Setup_5getcomm(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static struct PyMPIIntracommObject *__pyx_f_7pymusic_5Setup_getcomm(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, int __pyx_skip_dispatch) {
+  struct PyMPIIntracommObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("getcomm", 0);
+  /* Check if called by wrapper */
+  if (unlikely(__pyx_skip_dispatch)) ;
+  /* Check if overridden in Python */
+  else if (unlikely(Py_TYPE(((PyObject *)__pyx_v_self))->tp_dictoffset != 0)) {
+    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_getcomm); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 406; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    if (!PyCFunction_Check(__pyx_t_1) || (PyCFunction_GET_FUNCTION(__pyx_t_1) != (PyCFunction)__pyx_pw_7pymusic_5Setup_5getcomm)) {
+      __Pyx_XDECREF(((PyObject *)__pyx_r));
+      __Pyx_INCREF(__pyx_t_1);
+      __pyx_t_3 = __pyx_t_1; __pyx_t_4 = NULL;
+      if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+        if (likely(__pyx_t_4)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_4);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_3, function);
+        }
+      }
+      if (__pyx_t_4) {
+        __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 406; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      } else {
+        __pyx_t_2 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 406; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      }
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_6mpi4py_3MPI_Intracomm))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 406; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_r = ((struct PyMPIIntracommObject *)__pyx_t_2);
+      __pyx_t_2 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      goto __pyx_L0;
+    }
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  }
+
+  /* "pymusic.pyx":411
+ *         side of music
+ *         """
+ *         return self.comm             # <<<<<<<<<<<<<<
+ * 
+ *     cdef null(self):
+ */
+  __Pyx_XDECREF(((PyObject *)__pyx_r));
+  __Pyx_INCREF(((PyObject *)__pyx_v_self->comm));
+  __pyx_r = __pyx_v_self->comm;
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":406
+ *         self.null()
+ * 
+ *     cpdef MPI.Intracomm getcomm(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Get an MPI communicator between the processes on this current
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("pymusic.Setup.getcomm", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF((PyObject *)__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_5getcomm(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_7pymusic_5Setup_4getcomm[] = "\n        Get an MPI communicator between the processes on this current\n        side of music\n        ";
+static PyObject *__pyx_pw_7pymusic_5Setup_5getcomm(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("getcomm (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_5Setup_4getcomm(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_4getcomm(struct __pyx_obj_7pymusic_Setup *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("getcomm", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = ((PyObject *)__pyx_f_7pymusic_5Setup_getcomm(__pyx_v_self, 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 406; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Setup.getcomm", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":413
+ *         return self.comm
+ * 
+ *     cdef null(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Invalidate this object --- called when runtime is
+ */
+
+static PyObject *__pyx_f_7pymusic_5Setup_null(struct __pyx_obj_7pymusic_Setup *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("null", 0);
+
+  /* "pymusic.pyx":419
+ *         objects and clearing references to them.
+ *         """
+ *         self.ptr = NULL             # <<<<<<<<<<<<<<
+ *         self.comm = <MPI.Intracomm> MPI.COMM_NULL
+ *         self.ports = None
+ */
+  __pyx_v_self->ptr = NULL;
+
+  /* "pymusic.pyx":420
+ *         """
+ *         self.ptr = NULL
+ *         self.comm = <MPI.Intracomm> MPI.COMM_NULL             # <<<<<<<<<<<<<<
+ *         self.ports = None
+ * 
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MPI); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 420; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_COMM_NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 420; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = __pyx_t_2;
+  __Pyx_INCREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->comm);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->comm));
+  __pyx_v_self->comm = ((struct PyMPIIntracommObject *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":421
+ *         self.ptr = NULL
+ *         self.comm = <MPI.Intracomm> MPI.COMM_NULL
+ *         self.ports = None             # <<<<<<<<<<<<<<
+ * 
+ *     ####
+ */
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->ports);
+  __Pyx_DECREF(__pyx_v_self->ports);
+  __pyx_v_self->ports = ((PyObject*)Py_None);
+
+  /* "pymusic.pyx":413
+ *         return self.comm
+ * 
+ *     cdef null(self):             # <<<<<<<<<<<<<<
+ *         """
+ *         Invalidate this object --- called when runtime is
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("pymusic.Setup.null", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":424
+ * 
+ *     ####
+ *     def config(self, string var):             # <<<<<<<<<<<<<<
+ *         """
+ *         Get the value for var in config file.
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_7config(PyObject *__pyx_v_self, PyObject *__pyx_arg_var); /*proto*/
+static char __pyx_doc_7pymusic_5Setup_6config[] = "\n        Get the value for var in config file.\n        string var: configuration variable for current group of\n        processes, including default and inherited settings.\n        The value is returned as an int if it matches the patter,\n        otherwise a float, otherwise a string.\n        Throws UndefinedConfig error if no such variable is defined.\n        ";
+static PyObject *__pyx_pw_7pymusic_5Setup_7config(PyObject *__pyx_v_self, PyObject *__pyx_arg_var) {
+  std::string __pyx_v_var;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("config (wrapper)", 0);
+  assert(__pyx_arg_var); {
+    __pyx_v_var = __pyx_convert_string_from_py_std__string(__pyx_arg_var); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Setup.config", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_5Setup_6config(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self), ((std::string)__pyx_v_var));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_6config(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_var) {
+  std::string __pyx_v_vs;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
+  PyObject *__pyx_t_8 = NULL;
+  PyObject *__pyx_t_9 = NULL;
+  int __pyx_t_10;
+  double __pyx_t_11;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("config", 0);
+
+  /* "pymusic.pyx":435
+ *         cdef string vs
+ * 
+ *         if not self.ptr.config(var, &vs):             # <<<<<<<<<<<<<<
+ *             raise UndefinedConfig(var)
+ * 
+ */
+  __pyx_t_1 = ((!(__pyx_v_self->ptr->config(__pyx_v_var, (&__pyx_v_vs)) != 0)) != 0);
+  if (__pyx_t_1) {
+
+    /* "pymusic.pyx":436
+ * 
+ *         if not self.ptr.config(var, &vs):
+ *             raise UndefinedConfig(var)             # <<<<<<<<<<<<<<
+ * 
+ *         try: return int(vs)
+ */
+    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_UndefinedConfig); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = __pyx_convert_PyBytes_string_to_py_std__string(__pyx_v_var); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    if (!__pyx_t_5) {
+      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_GOTREF(__pyx_t_2);
+    } else {
+      __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_6);
+      PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_5); __Pyx_GIVEREF(__pyx_t_5); __pyx_t_5 = NULL;
+      PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_t_4);
+      __Pyx_GIVEREF(__pyx_t_4);
+      __pyx_t_4 = 0;
+      __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_6, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    }
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+
+  /* "pymusic.pyx":438
+ *             raise UndefinedConfig(var)
+ * 
+ *         try: return int(vs)             # <<<<<<<<<<<<<<
+ *         except ValueError: pass
+ * 
+ */
+  {
+    __Pyx_ExceptionSave(&__pyx_t_7, &__pyx_t_8, &__pyx_t_9);
+    __Pyx_XGOTREF(__pyx_t_7);
+    __Pyx_XGOTREF(__pyx_t_8);
+    __Pyx_XGOTREF(__pyx_t_9);
+    /*try:*/ {
+      __Pyx_XDECREF(__pyx_r);
+      __pyx_t_2 = __pyx_convert_PyBytes_string_to_py_std__string(__pyx_v_vs); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 438; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 438; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);
+      __Pyx_GIVEREF(__pyx_t_2);
+      __pyx_t_2 = 0;
+      __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)(&PyInt_Type))), __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 438; __pyx_clineno = __LINE__; goto __pyx_L4_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_r = __pyx_t_2;
+      __pyx_t_2 = 0;
+      goto __pyx_L8_try_return;
+    }
+    __pyx_L4_error:;
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+    /* "pymusic.pyx":439
+ * 
+ *         try: return int(vs)
+ *         except ValueError: pass             # <<<<<<<<<<<<<<
+ * 
+ *         try: return float(vs)
+ */
+    __pyx_t_10 = PyErr_ExceptionMatches(__pyx_builtin_ValueError);
+    if (__pyx_t_10) {
+      PyErr_Restore(0,0,0);
+      goto __pyx_L5_exception_handled;
+    }
+    goto __pyx_L6_except_error;
+    __pyx_L6_except_error:;
+    __Pyx_XGIVEREF(__pyx_t_7);
+    __Pyx_XGIVEREF(__pyx_t_8);
+    __Pyx_XGIVEREF(__pyx_t_9);
+    __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9);
+    goto __pyx_L1_error;
+    __pyx_L8_try_return:;
+    __Pyx_XGIVEREF(__pyx_t_7);
+    __Pyx_XGIVEREF(__pyx_t_8);
+    __Pyx_XGIVEREF(__pyx_t_9);
+    __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9);
+    goto __pyx_L0;
+    __pyx_L5_exception_handled:;
+    __Pyx_XGIVEREF(__pyx_t_7);
+    __Pyx_XGIVEREF(__pyx_t_8);
+    __Pyx_XGIVEREF(__pyx_t_9);
+    __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9);
+  }
+
+  /* "pymusic.pyx":441
+ *         except ValueError: pass
+ * 
+ *         try: return float(vs)             # <<<<<<<<<<<<<<
+ *         except ValueError: pass
+ * 
+ */
+  {
+    __Pyx_ExceptionSave(&__pyx_t_9, &__pyx_t_8, &__pyx_t_7);
+    __Pyx_XGOTREF(__pyx_t_9);
+    __Pyx_XGOTREF(__pyx_t_8);
+    __Pyx_XGOTREF(__pyx_t_7);
+    /*try:*/ {
+      __Pyx_XDECREF(__pyx_r);
+      __pyx_t_2 = __pyx_convert_PyBytes_string_to_py_std__string(__pyx_v_vs); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 441; __pyx_clineno = __LINE__; goto __pyx_L12_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_11 = __Pyx_PyObject_AsDouble(__pyx_t_2); if (unlikely(__pyx_t_11 == ((double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 441; __pyx_clineno = __LINE__; goto __pyx_L12_error;}
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __pyx_t_2 = PyFloat_FromDouble(__pyx_t_11); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 441; __pyx_clineno = __LINE__; goto __pyx_L12_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_r = __pyx_t_2;
+      __pyx_t_2 = 0;
+      goto __pyx_L16_try_return;
+    }
+    __pyx_L12_error:;
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+    /* "pymusic.pyx":442
+ * 
+ *         try: return float(vs)
+ *         except ValueError: pass             # <<<<<<<<<<<<<<
+ * 
+ *         return vs
+ */
+    __pyx_t_10 = PyErr_ExceptionMatches(__pyx_builtin_ValueError);
+    if (__pyx_t_10) {
+      PyErr_Restore(0,0,0);
+      goto __pyx_L13_exception_handled;
+    }
+    goto __pyx_L14_except_error;
+    __pyx_L14_except_error:;
+    __Pyx_XGIVEREF(__pyx_t_9);
+    __Pyx_XGIVEREF(__pyx_t_8);
+    __Pyx_XGIVEREF(__pyx_t_7);
+    __Pyx_ExceptionReset(__pyx_t_9, __pyx_t_8, __pyx_t_7);
+    goto __pyx_L1_error;
+    __pyx_L16_try_return:;
+    __Pyx_XGIVEREF(__pyx_t_9);
+    __Pyx_XGIVEREF(__pyx_t_8);
+    __Pyx_XGIVEREF(__pyx_t_7);
+    __Pyx_ExceptionReset(__pyx_t_9, __pyx_t_8, __pyx_t_7);
+    goto __pyx_L0;
+    __pyx_L13_exception_handled:;
+    __Pyx_XGIVEREF(__pyx_t_9);
+    __Pyx_XGIVEREF(__pyx_t_8);
+    __Pyx_XGIVEREF(__pyx_t_7);
+    __Pyx_ExceptionReset(__pyx_t_9, __pyx_t_8, __pyx_t_7);
+  }
+
+  /* "pymusic.pyx":444
+ *         except ValueError: pass
+ * 
+ *         return vs             # <<<<<<<<<<<<<<
+ *     ####
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_2 = __pyx_convert_PyBytes_string_to_py_std__string(__pyx_v_vs); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_r = __pyx_t_2;
+  __pyx_t_2 = 0;
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":424
+ * 
+ *     ####
+ *     def config(self, string var):             # <<<<<<<<<<<<<<
+ *         """
+ *         Get the value for var in config file.
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_AddTraceback("pymusic.Setup.config", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":447
+ *     ####
+ * 
+ *     def publishContInput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Continuous Floating point value sink
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_9publishContInput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s); /*proto*/
+static char __pyx_doc_7pymusic_5Setup_8publishContInput[] = "\n        Continuous Floating point value sink\n        string s: port name for music config\n        ";
+static PyObject *__pyx_pw_7pymusic_5Setup_9publishContInput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s) {
+  std::string __pyx_v_s;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("publishContInput (wrapper)", 0);
+  assert(__pyx_arg_s); {
+    __pyx_v_s = __pyx_convert_string_from_py_std__string(__pyx_arg_s); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Setup.publishContInput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_5Setup_8publishContInput(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self), ((std::string)__pyx_v_s));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_8publishContInput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s) {
+  struct __pyx_obj_7pymusic_ContInputPort *__pyx_v_p = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("publishContInput", 0);
+
+  /* "pymusic.pyx":452
+ *         string s: port name for music config
+ *         """
+ *         cdef ContInputPort p = ContInputPort()             # <<<<<<<<<<<<<<
+ *         p.ptr = self.ptr.publishContInput(s) # can't pass pointers directly to init
+ *         self.ports.add(p)
+ */
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_ContInputPort)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_p = ((struct __pyx_obj_7pymusic_ContInputPort *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":453
+ *         """
+ *         cdef ContInputPort p = ContInputPort()
+ *         p.ptr = self.ptr.publishContInput(s) # can't pass pointers directly to init             # <<<<<<<<<<<<<<
+ *         self.ports.add(p)
+ *         return p
+ */
+  __pyx_v_p->__pyx_base.ptr = __pyx_v_self->ptr->publishContInput(__pyx_v_s);
+
+  /* "pymusic.pyx":454
+ *         cdef ContInputPort p = ContInputPort()
+ *         p.ptr = self.ptr.publishContInput(s) # can't pass pointers directly to init
+ *         self.ports.add(p)             # <<<<<<<<<<<<<<
+ *         return p
+ * 
+ */
+  if (unlikely(__pyx_v_self->ports == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "add");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_2 = PySet_Add(__pyx_v_self->ports, ((PyObject *)__pyx_v_p)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":455
+ *         p.ptr = self.ptr.publishContInput(s) # can't pass pointers directly to init
+ *         self.ports.add(p)
+ *         return p             # <<<<<<<<<<<<<<
+ * 
+ *     def publishContOutput(self, string s):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_p));
+  __pyx_r = ((PyObject *)__pyx_v_p);
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":447
+ *     ####
+ * 
+ *     def publishContInput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Continuous Floating point value sink
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Setup.publishContInput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_p);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":457
+ *         return p
+ * 
+ *     def publishContOutput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Continuous Floating point value source
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_11publishContOutput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s); /*proto*/
+static char __pyx_doc_7pymusic_5Setup_10publishContOutput[] = "\n        Continuous Floating point value source\n        string s: port name for music config\n        ";
+static PyObject *__pyx_pw_7pymusic_5Setup_11publishContOutput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s) {
+  std::string __pyx_v_s;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("publishContOutput (wrapper)", 0);
+  assert(__pyx_arg_s); {
+    __pyx_v_s = __pyx_convert_string_from_py_std__string(__pyx_arg_s); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 457; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Setup.publishContOutput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_5Setup_10publishContOutput(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self), ((std::string)__pyx_v_s));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_10publishContOutput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s) {
+  struct __pyx_obj_7pymusic_ContOutputPort *__pyx_v_p = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("publishContOutput", 0);
+
+  /* "pymusic.pyx":462
+ *         string s: port name for music config
+ *         """
+ *         cdef ContOutputPort p = ContOutputPort()             # <<<<<<<<<<<<<<
+ *         p.ptr = self.ptr.publishContOutput(s)
+ *         self.ports.add(p)
+ */
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_ContOutputPort)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 462; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_p = ((struct __pyx_obj_7pymusic_ContOutputPort *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":463
+ *         """
+ *         cdef ContOutputPort p = ContOutputPort()
+ *         p.ptr = self.ptr.publishContOutput(s)             # <<<<<<<<<<<<<<
+ *         self.ports.add(p)
+ *         return p
+ */
+  __pyx_v_p->__pyx_base.ptr = __pyx_v_self->ptr->publishContOutput(__pyx_v_s);
+
+  /* "pymusic.pyx":464
+ *         cdef ContOutputPort p = ContOutputPort()
+ *         p.ptr = self.ptr.publishContOutput(s)
+ *         self.ports.add(p)             # <<<<<<<<<<<<<<
+ *         return p
+ * 
+ */
+  if (unlikely(__pyx_v_self->ports == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "add");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 464; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_2 = PySet_Add(__pyx_v_self->ports, ((PyObject *)__pyx_v_p)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 464; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":465
+ *         p.ptr = self.ptr.publishContOutput(s)
+ *         self.ports.add(p)
+ *         return p             # <<<<<<<<<<<<<<
+ * 
+ *     def publishEventOutput(self, string s):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_p));
+  __pyx_r = ((PyObject *)__pyx_v_p);
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":457
+ *         return p
+ * 
+ *     def publishContOutput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Continuous Floating point value source
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Setup.publishContOutput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_p);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":467
+ *         return p
+ * 
+ *     def publishEventOutput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Discrete boolean source
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_13publishEventOutput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s); /*proto*/
+static char __pyx_doc_7pymusic_5Setup_12publishEventOutput[] = "\n        Discrete boolean source\n        string s: port name for music config\n        ";
+static PyObject *__pyx_pw_7pymusic_5Setup_13publishEventOutput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s) {
+  std::string __pyx_v_s;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("publishEventOutput (wrapper)", 0);
+  assert(__pyx_arg_s); {
+    __pyx_v_s = __pyx_convert_string_from_py_std__string(__pyx_arg_s); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 467; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Setup.publishEventOutput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_5Setup_12publishEventOutput(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self), ((std::string)__pyx_v_s));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_12publishEventOutput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s) {
+  struct __pyx_obj_7pymusic_EventOutputPort *__pyx_v_p = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("publishEventOutput", 0);
+
+  /* "pymusic.pyx":472
+ *         string s: port name for music config
+ *         """
+ *         cdef EventOutputPort p = EventOutputPort()             # <<<<<<<<<<<<<<
+ *         p.ptr = self.ptr.publishEventOutput(s)
+ *         self.ports.add(p)
+ */
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_EventOutputPort)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 472; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_p = ((struct __pyx_obj_7pymusic_EventOutputPort *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":473
+ *         """
+ *         cdef EventOutputPort p = EventOutputPort()
+ *         p.ptr = self.ptr.publishEventOutput(s)             # <<<<<<<<<<<<<<
+ *         self.ports.add(p)
+ *         return p
+ */
+  __pyx_v_p->__pyx_base.ptr = __pyx_v_self->ptr->publishEventOutput(__pyx_v_s);
+
+  /* "pymusic.pyx":474
+ *         cdef EventOutputPort p = EventOutputPort()
+ *         p.ptr = self.ptr.publishEventOutput(s)
+ *         self.ports.add(p)             # <<<<<<<<<<<<<<
+ *         return p
+ * 
+ */
+  if (unlikely(__pyx_v_self->ports == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "add");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_2 = PySet_Add(__pyx_v_self->ports, ((PyObject *)__pyx_v_p)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 474; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":475
+ *         p.ptr = self.ptr.publishEventOutput(s)
+ *         self.ports.add(p)
+ *         return p             # <<<<<<<<<<<<<<
+ * 
+ *     def publishEventInput(self, string s):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_p));
+  __pyx_r = ((PyObject *)__pyx_v_p);
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":467
+ *         return p
+ * 
+ *     def publishEventOutput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Discrete boolean source
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Setup.publishEventOutput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_p);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":477
+ *         return p
+ * 
+ *     def publishEventInput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Discrete boolean sink
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_15publishEventInput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s); /*proto*/
+static char __pyx_doc_7pymusic_5Setup_14publishEventInput[] = "\n        Discrete boolean sink\n        string s: port name for music config\n        ";
+static PyObject *__pyx_pw_7pymusic_5Setup_15publishEventInput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s) {
+  std::string __pyx_v_s;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("publishEventInput (wrapper)", 0);
+  assert(__pyx_arg_s); {
+    __pyx_v_s = __pyx_convert_string_from_py_std__string(__pyx_arg_s); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 477; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Setup.publishEventInput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_5Setup_14publishEventInput(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self), ((std::string)__pyx_v_s));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_14publishEventInput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s) {
+  struct __pyx_obj_7pymusic_EventInputPort *__pyx_v_p = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("publishEventInput", 0);
+
+  /* "pymusic.pyx":482
+ *         string s: port name for music config
+ *         """
+ *         cdef EventInputPort p = EventInputPort()             # <<<<<<<<<<<<<<
+ *         p.ptr = self.ptr.publishEventInput(s)
+ *         self.ports.add(p)
+ */
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_EventInputPort)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 482; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_p = ((struct __pyx_obj_7pymusic_EventInputPort *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":483
+ *         """
+ *         cdef EventInputPort p = EventInputPort()
+ *         p.ptr = self.ptr.publishEventInput(s)             # <<<<<<<<<<<<<<
+ *         self.ports.add(p)
+ *         return p
+ */
+  __pyx_v_p->__pyx_base.ptr = __pyx_v_self->ptr->publishEventInput(__pyx_v_s);
+
+  /* "pymusic.pyx":484
+ *         cdef EventInputPort p = EventInputPort()
+ *         p.ptr = self.ptr.publishEventInput(s)
+ *         self.ports.add(p)             # <<<<<<<<<<<<<<
+ *         return p
+ * 
+ */
+  if (unlikely(__pyx_v_self->ports == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "add");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 484; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_2 = PySet_Add(__pyx_v_self->ports, ((PyObject *)__pyx_v_p)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 484; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":485
+ *         p.ptr = self.ptr.publishEventInput(s)
+ *         self.ports.add(p)
+ *         return p             # <<<<<<<<<<<<<<
+ * 
+ *     def publishMessageOutput(self, string s):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_p));
+  __pyx_r = ((PyObject *)__pyx_v_p);
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":477
+ *         return p
+ * 
+ *     def publishEventInput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Discrete boolean sink
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Setup.publishEventInput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_p);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":487
+ *         return p
+ * 
+ *     def publishMessageOutput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Discrete python object source
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_17publishMessageOutput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s); /*proto*/
+static char __pyx_doc_7pymusic_5Setup_16publishMessageOutput[] = "\n        Discrete python object source\n        string s: port name for music config\n        ";
+static PyObject *__pyx_pw_7pymusic_5Setup_17publishMessageOutput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s) {
+  std::string __pyx_v_s;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("publishMessageOutput (wrapper)", 0);
+  assert(__pyx_arg_s); {
+    __pyx_v_s = __pyx_convert_string_from_py_std__string(__pyx_arg_s); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 487; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Setup.publishMessageOutput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_5Setup_16publishMessageOutput(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self), ((std::string)__pyx_v_s));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_16publishMessageOutput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s) {
+  struct __pyx_obj_7pymusic_MessageOutputPort *__pyx_v_p = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("publishMessageOutput", 0);
+
+  /* "pymusic.pyx":492
+ *         string s: port name for music config
+ *         """
+ *         cdef MessageOutputPort p = MessageOutputPort()             # <<<<<<<<<<<<<<
+ *         p.ptr = self.ptr.publishMessageOutput(s)
+ *         self.ports.add(p)
+ */
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_MessageOutputPort)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 492; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_p = ((struct __pyx_obj_7pymusic_MessageOutputPort *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":493
+ *         """
+ *         cdef MessageOutputPort p = MessageOutputPort()
+ *         p.ptr = self.ptr.publishMessageOutput(s)             # <<<<<<<<<<<<<<
+ *         self.ports.add(p)
+ *         return p
+ */
+  __pyx_v_p->__pyx_base.ptr = __pyx_v_self->ptr->publishMessageOutput(__pyx_v_s);
+
+  /* "pymusic.pyx":494
+ *         cdef MessageOutputPort p = MessageOutputPort()
+ *         p.ptr = self.ptr.publishMessageOutput(s)
+ *         self.ports.add(p)             # <<<<<<<<<<<<<<
+ *         return p
+ * 
+ */
+  if (unlikely(__pyx_v_self->ports == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "add");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_2 = PySet_Add(__pyx_v_self->ports, ((PyObject *)__pyx_v_p)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 494; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":495
+ *         p.ptr = self.ptr.publishMessageOutput(s)
+ *         self.ports.add(p)
+ *         return p             # <<<<<<<<<<<<<<
+ * 
+ *     def publishMessageInput(self, string s):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_p));
+  __pyx_r = ((PyObject *)__pyx_v_p);
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":487
+ *         return p
+ * 
+ *     def publishMessageOutput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Discrete python object source
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Setup.publishMessageOutput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_p);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":497
+ *         return p
+ * 
+ *     def publishMessageInput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Discrete python object sink
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_19publishMessageInput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s); /*proto*/
+static char __pyx_doc_7pymusic_5Setup_18publishMessageInput[] = "\n        Discrete python object sink\n        string s: port name for music config\n        ";
+static PyObject *__pyx_pw_7pymusic_5Setup_19publishMessageInput(PyObject *__pyx_v_self, PyObject *__pyx_arg_s) {
+  std::string __pyx_v_s;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("publishMessageInput (wrapper)", 0);
+  assert(__pyx_arg_s); {
+    __pyx_v_s = __pyx_convert_string_from_py_std__string(__pyx_arg_s); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 497; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Setup.publishMessageInput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_5Setup_18publishMessageInput(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self), ((std::string)__pyx_v_s));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_18publishMessageInput(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, std::string __pyx_v_s) {
+  struct __pyx_obj_7pymusic_MessageInputPort *__pyx_v_p = 0;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("publishMessageInput", 0);
+
+  /* "pymusic.pyx":502
+ *         string s: port name for music config
+ *         """
+ *         cdef MessageInputPort p = MessageInputPort()             # <<<<<<<<<<<<<<
+ *         p.ptr = self.ptr.publishMessageInput(s)
+ *         self.ports.add(p)
+ */
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_MessageInputPort)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 502; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_p = ((struct __pyx_obj_7pymusic_MessageInputPort *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":503
+ *         """
+ *         cdef MessageInputPort p = MessageInputPort()
+ *         p.ptr = self.ptr.publishMessageInput(s)             # <<<<<<<<<<<<<<
+ *         self.ports.add(p)
+ *         return p
+ */
+  __pyx_v_p->__pyx_base.ptr = __pyx_v_self->ptr->publishMessageInput(__pyx_v_s);
+
+  /* "pymusic.pyx":504
+ *         cdef MessageInputPort p = MessageInputPort()
+ *         p.ptr = self.ptr.publishMessageInput(s)
+ *         self.ports.add(p)             # <<<<<<<<<<<<<<
+ *         return p
+ * 
+ */
+  if (unlikely(__pyx_v_self->ports == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "add");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_2 = PySet_Add(__pyx_v_self->ports, ((PyObject *)__pyx_v_p)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 504; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":505
+ *         p.ptr = self.ptr.publishMessageInput(s)
+ *         self.ports.add(p)
+ *         return p             # <<<<<<<<<<<<<<
+ * 
+ *     def runtime(self, double timestep):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_p));
+  __pyx_r = ((PyObject *)__pyx_v_p);
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":497
+ *         return p
+ * 
+ *     def publishMessageInput(self, string s):             # <<<<<<<<<<<<<<
+ *         """
+ *         Discrete python object sink
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Setup.publishMessageInput", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_p);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":507
+ *         return p
+ * 
+ *     def runtime(self, double timestep):             # <<<<<<<<<<<<<<
+ *         """
+ *         Create a runtime.
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_21runtime(PyObject *__pyx_v_self, PyObject *__pyx_arg_timestep); /*proto*/
+static char __pyx_doc_7pymusic_5Setup_20runtime[] = "\n        Create a runtime.\n        After return, this Setup object is invalid\n        double timestep: size of timestep (\077\077 units)\n        ";
+static PyObject *__pyx_pw_7pymusic_5Setup_21runtime(PyObject *__pyx_v_self, PyObject *__pyx_arg_timestep) {
+  double __pyx_v_timestep;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("runtime (wrapper)", 0);
+  assert(__pyx_arg_timestep); {
+    __pyx_v_timestep = __pyx_PyFloat_AsDouble(__pyx_arg_timestep); if (unlikely((__pyx_v_timestep == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 507; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Setup.runtime", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_5Setup_20runtime(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self), ((double)__pyx_v_timestep));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_20runtime(struct __pyx_obj_7pymusic_Setup *__pyx_v_self, double __pyx_v_timestep) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("runtime", 0);
+
+  /* "pymusic.pyx":513
+ *         double timestep: size of timestep (?? units)
+ *         """
+ *         return Runtime(self, timestep)             # <<<<<<<<<<<<<<
+ * 
+ * ###########################################################
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_timestep); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 513; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 513; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_self));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+  PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic_Runtime)), __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 513; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":507
+ *         return p
+ * 
+ *     def runtime(self, double timestep):             # <<<<<<<<<<<<<<
+ *         """
+ *         Create a runtime.
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("pymusic.Setup.runtime", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pxd":168
+ *     cdef list argv
+ *     cdef int provided
+ *     cdef readonly MPI.Intracomm comm             # <<<<<<<<<<<<<<
+ *     cdef set ports
+ * 
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_5Setup_4comm_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_7pymusic_5Setup_4comm_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_5Setup_4comm___get__(((struct __pyx_obj_7pymusic_Setup *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_5Setup_4comm___get__(struct __pyx_obj_7pymusic_Setup *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self->comm));
+  __pyx_r = ((PyObject *)__pyx_v_self->comm);
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":518
+ * 
+ * cdef class Runtime(object):
+ *     def __cinit__(self, Setup setup, double h):             # <<<<<<<<<<<<<<
+ *         self.ptr = new CRuntime(setup.ptr, h)
+ *         self.ports = setup.ports
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_7Runtime_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_7Runtime_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  struct __pyx_obj_7pymusic_Setup *__pyx_v_setup = 0;
+  double __pyx_v_h;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_setup,&__pyx_n_s_h,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_setup)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_h)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_setup = ((struct __pyx_obj_7pymusic_Setup *)values[0]);
+    __pyx_v_h = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_h == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.Runtime.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_setup), __pyx_ptype_7pymusic_Setup, 1, "setup", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 518; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_7pymusic_7Runtime___cinit__(((struct __pyx_obj_7pymusic_Runtime *)__pyx_v_self), __pyx_v_setup, __pyx_v_h);
+
+  /* function exit code */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_7Runtime___cinit__(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self, struct __pyx_obj_7pymusic_Setup *__pyx_v_setup, double __pyx_v_h) {
+  struct PyMPIIntracommObject *__pyx_v_comm = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  MUSIC::Runtime *__pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":519
+ * cdef class Runtime(object):
+ *     def __cinit__(self, Setup setup, double h):
+ *         self.ptr = new CRuntime(setup.ptr, h)             # <<<<<<<<<<<<<<
+ *         self.ports = setup.ports
+ *         setup.null()
+ */
+  try {
+    __pyx_t_1 = new MUSIC::Runtime(__pyx_v_setup->ptr, __pyx_v_h);
+  } catch(...) {
+    __Pyx_CppExn2PyErr();
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 519; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_v_self->ptr = __pyx_t_1;
+
+  /* "pymusic.pyx":520
+ *     def __cinit__(self, Setup setup, double h):
+ *         self.ptr = new CRuntime(setup.ptr, h)
+ *         self.ports = setup.ports             # <<<<<<<<<<<<<<
+ *         setup.null()
+ * 
+ */
+  __pyx_t_2 = __pyx_v_setup->ports;
+  __Pyx_INCREF(__pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __Pyx_GOTREF(__pyx_v_self->ports);
+  __Pyx_DECREF(__pyx_v_self->ports);
+  __pyx_v_self->ports = ((PyObject*)__pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":521
+ *         self.ptr = new CRuntime(setup.ptr, h)
+ *         self.ports = setup.ports
+ *         setup.null()             # <<<<<<<<<<<<<<
+ * 
+ *         cdef MPI.Intracomm comm = MPI.Intracomm()
+ */
+  __pyx_t_2 = ((struct __pyx_vtabstruct_7pymusic_Setup *)__pyx_v_setup->__pyx_vtab)->null(__pyx_v_setup); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 521; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":523
+ *         setup.null()
+ * 
+ *         cdef MPI.Intracomm comm = MPI.Intracomm()             # <<<<<<<<<<<<<<
+ *         comm.ob_mpi = communicator(self.ptr)
+ *         self.comm = comm
+ */
+  __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_6mpi4py_3MPI_Intracomm)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 523; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_v_comm = ((struct PyMPIIntracommObject *)__pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":524
+ * 
+ *         cdef MPI.Intracomm comm = MPI.Intracomm()
+ *         comm.ob_mpi = communicator(self.ptr)             # <<<<<<<<<<<<<<
+ *         self.comm = comm
+ * 
+ */
+  __pyx_v_comm->__pyx_base.ob_mpi = MUSIC::communicator(__pyx_v_self->ptr);
+
+  /* "pymusic.pyx":525
+ *         cdef MPI.Intracomm comm = MPI.Intracomm()
+ *         comm.ob_mpi = communicator(self.ptr)
+ *         self.comm = comm             # <<<<<<<<<<<<<<
+ * 
+ *     def __dealloc__(self):
+ */
+  __Pyx_INCREF(((PyObject *)__pyx_v_comm));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_comm));
+  __Pyx_GOTREF(__pyx_v_self->comm);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->comm));
+  __pyx_v_self->comm = __pyx_v_comm;
+
+  /* "pymusic.pyx":518
+ * 
+ * cdef class Runtime(object):
+ *     def __cinit__(self, Setup setup, double h):             # <<<<<<<<<<<<<<
+ *         self.ptr = new CRuntime(setup.ptr, h)
+ *         self.ports = setup.ports
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("pymusic.Runtime.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_comm);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":527
+ *         self.comm = comm
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         self.ptr.finalize()
+ * 
+ */
+
+/* Python wrapper */
+static void __pyx_pw_7pymusic_7Runtime_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_7pymusic_7Runtime_3__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_7pymusic_7Runtime_2__dealloc__(((struct __pyx_obj_7pymusic_Runtime *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+static void __pyx_pf_7pymusic_7Runtime_2__dealloc__(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self) {
+  PyObject *__pyx_v_p = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *(*__pyx_t_2)(PyObject *);
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
+
+  /* "pymusic.pyx":528
+ * 
+ *     def __dealloc__(self):
+ *         self.ptr.finalize()             # <<<<<<<<<<<<<<
+ * 
+ *         for p in self.ports:
+ */
+  __pyx_v_self->ptr->finalize();
+
+  /* "pymusic.pyx":530
+ *         self.ptr.finalize()
+ * 
+ *         for p in self.ports:             # <<<<<<<<<<<<<<
+ *             p.null()
+ * 
+ */
+  __pyx_t_1 = PyObject_GetIter(__pyx_v_self->ports); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  for (;;) {
+    {
+      __pyx_t_3 = __pyx_t_2(__pyx_t_1);
+      if (unlikely(!__pyx_t_3)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 530; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_3);
+    }
+    __Pyx_XDECREF_SET(__pyx_v_p, __pyx_t_3);
+    __pyx_t_3 = 0;
+
+    /* "pymusic.pyx":531
+ * 
+ *         for p in self.ports:
+ *             p.null()             # <<<<<<<<<<<<<<
+ * 
+ *         del self.ptr
+ */
+    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_p, __pyx_n_s_null); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    if (__pyx_t_5) {
+      __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    } else {
+      __pyx_t_3 = __Pyx_PyObject_CallNoArg(__pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 531; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+    /* "pymusic.pyx":530
+ *         self.ptr.finalize()
+ * 
+ *         for p in self.ports:             # <<<<<<<<<<<<<<
+ *             p.null()
+ * 
+ */
+  }
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":533
+ *             p.null()
+ * 
+ *         del self.ptr             # <<<<<<<<<<<<<<
+ * 
+ *     def time(self): return self.ptr.time()
+ */
+  delete __pyx_v_self->ptr;
+
+  /* "pymusic.pyx":527
+ *         self.comm = comm
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         self.ptr.finalize()
+ * 
+ */
+
+  /* function exit code */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_WriteUnraisable("pymusic.Runtime.__dealloc__", __pyx_clineno, __pyx_lineno, __pyx_filename, 0);
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_p);
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "pymusic.pyx":535
+ *         del self.ptr
+ * 
+ *     def time(self): return self.ptr.time()             # <<<<<<<<<<<<<<
+ *     def tick(self): tick(self.ptr)
+ * 
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_7Runtime_5time(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_7pymusic_7Runtime_5time(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("time (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_7Runtime_4time(((struct __pyx_obj_7pymusic_Runtime *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_7Runtime_4time(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("time", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_self->ptr->time()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 535; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic.Runtime.time", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":536
+ * 
+ *     def time(self): return self.ptr.time()
+ *     def tick(self): tick(self.ptr)             # <<<<<<<<<<<<<<
+ * 
+ *     def __iter__(self):
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_7Runtime_7tick(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_7pymusic_7Runtime_7tick(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("tick (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_7Runtime_6tick(((struct __pyx_obj_7pymusic_Runtime *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_7Runtime_6tick(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  bool __pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("tick", 0);
+  __pyx_t_1 = MUSIC::tick(__pyx_v_self->ptr); if (unlikely(__pyx_t_1 == 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 536; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("pymusic.Runtime.tick", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+static PyObject *__pyx_gb_7pymusic_7Runtime_10generator(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value); /* proto */
+
+/* "pymusic.pyx":538
+ *     def tick(self): tick(self.ptr)
+ * 
+ *     def __iter__(self):             # <<<<<<<<<<<<<<
+ *         cdef CRuntime* ptr = self.ptr
+ *         while True:
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_7Runtime_9__iter__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_7pymusic_7Runtime_9__iter__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__iter__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_7Runtime_8__iter__(((struct __pyx_obj_7pymusic_Runtime *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_7Runtime_8__iter__(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self) {
+  struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *__pyx_cur_scope;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__iter__", 0);
+  __pyx_cur_scope = (struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *)__pyx_tp_new_7pymusic___pyx_scope_struct____iter__(__pyx_ptype_7pymusic___pyx_scope_struct____iter__, __pyx_empty_tuple, NULL);
+  if (unlikely(!__pyx_cur_scope)) {
+    __Pyx_RefNannyFinishContext();
+    return NULL;
+  }
+  __Pyx_GOTREF(__pyx_cur_scope);
+  __pyx_cur_scope->__pyx_v_self = __pyx_v_self;
+  __Pyx_INCREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
+  __Pyx_GIVEREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
+  {
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_7pymusic_7Runtime_10generator, (PyObject *) __pyx_cur_scope, __pyx_n_s_iter, __pyx_n_s_Runtime___iter); if (unlikely(!gen)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 538; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_cur_scope);
+    __Pyx_RefNannyFinishContext();
+    return (PyObject *) gen;
+  }
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("pymusic.Runtime.__iter__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_gb_7pymusic_7Runtime_10generator(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value) /* generator body */
+{
+  struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *__pyx_cur_scope = ((struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *)__pyx_generator->closure);
+  PyObject *__pyx_r = NULL;
+  MUSIC::Runtime *__pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  bool __pyx_t_3;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("None", 0);
+  switch (__pyx_generator->resume_label) {
+    case 0: goto __pyx_L3_first_run;
+    case 1: goto __pyx_L6_resume_from_yield;
+    default: /* CPython raises the right error here */
+    __Pyx_RefNannyFinishContext();
+    return NULL;
+  }
+  __pyx_L3_first_run:;
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 538; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":539
+ * 
+ *     def __iter__(self):
+ *         cdef CRuntime* ptr = self.ptr             # <<<<<<<<<<<<<<
+ *         while True:
+ *             yield ptr.time()
+ */
+  __pyx_t_1 = __pyx_cur_scope->__pyx_v_self->ptr;
+  __pyx_cur_scope->__pyx_v_ptr = __pyx_t_1;
+
+  /* "pymusic.pyx":540
+ *     def __iter__(self):
+ *         cdef CRuntime* ptr = self.ptr
+ *         while True:             # <<<<<<<<<<<<<<
+ *             yield ptr.time()
+ *             tick(ptr)
+ */
+  while (1) {
+
+    /* "pymusic.pyx":541
+ *         cdef CRuntime* ptr = self.ptr
+ *         while True:
+ *             yield ptr.time()             # <<<<<<<<<<<<<<
+ *             tick(ptr)
+ * 
+ */
+    __pyx_t_2 = PyFloat_FromDouble(__pyx_cur_scope->__pyx_v_ptr->time()); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_r = __pyx_t_2;
+    __pyx_t_2 = 0;
+    __Pyx_XGIVEREF(__pyx_r);
+    __Pyx_RefNannyFinishContext();
+    /* return from generator, yielding value */
+    __pyx_generator->resume_label = 1;
+    return __pyx_r;
+    __pyx_L6_resume_from_yield:;
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 541; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+    /* "pymusic.pyx":542
+ *         while True:
+ *             yield ptr.time()
+ *             tick(ptr)             # <<<<<<<<<<<<<<
+ * 
+ * ###########################################################
+ */
+    __pyx_t_3 = MUSIC::tick(__pyx_cur_scope->__pyx_v_ptr); if (unlikely(__pyx_t_3 == 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 542; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+
+  /* "pymusic.pyx":538
+ *     def tick(self): tick(self.ptr)
+ * 
+ *     def __iter__(self):             # <<<<<<<<<<<<<<
+ *         cdef CRuntime* ptr = self.ptr
+ *         while True:
+ */
+
+  /* function exit code */
+  PyErr_SetNone(PyExc_StopIteration);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("__iter__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_generator->resume_label = -1;
+  __Pyx_Generator_clear((PyObject*)__pyx_generator);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+}
+
+/* "pymusic.pxd":178
+ * cdef class Runtime(object):
+ *     cdef CRuntime* ptr
+ *     cdef readonly MPI.Intracomm comm             # <<<<<<<<<<<<<<
+ *     cdef set ports
+ * 
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_7Runtime_4comm_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_7pymusic_7Runtime_4comm_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_7Runtime_4comm___get__(((struct __pyx_obj_7pymusic_Runtime *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_7Runtime_4comm___get__(struct __pyx_obj_7pymusic_Runtime *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self->comm));
+  __pyx_r = ((PyObject *)__pyx_v_self->comm);
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":559
+ *     PermutationIndex: g = perm[l], where perm is an array
+ *     """
+ *     def __cinit__(self, object perm=None, int base=0, int size=-1):             # <<<<<<<<<<<<<<
+ *         """
+ *         Created internally
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_8IndexMap_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_8IndexMap_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_perm = 0;
+  int __pyx_v_base;
+  int __pyx_v_size;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_perm,&__pyx_n_s_base,&__pyx_n_s_size,0};
+    PyObject* values[3] = {0,0,0};
+    values[0] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_perm);
+          if (value) { values[0] = value; kw_args--; }
+        }
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_base);
+          if (value) { values[1] = value; kw_args--; }
+        }
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_size);
+          if (value) { values[2] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_perm = values[0];
+    if (values[1]) {
+      __pyx_v_base = __Pyx_PyInt_As_int(values[1]); if (unlikely((__pyx_v_base == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_base = ((int)0);
+    }
+    if (values[2]) {
+      __pyx_v_size = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_size = ((int)-1);
+    }
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 559; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.IndexMap.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_8IndexMap___cinit__(((struct __pyx_obj_7pymusic_IndexMap *)__pyx_v_self), __pyx_v_perm, __pyx_v_base, __pyx_v_size);
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_8IndexMap___cinit__(struct __pyx_obj_7pymusic_IndexMap *__pyx_v_self, PyObject *__pyx_v_perm, int __pyx_v_base, int __pyx_v_size) {
+  arrayobject *__pyx_v_arr = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  int __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  Py_ssize_t __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":570
+ *         cdef array.array arr
+ * 
+ *         if perm is None:             # <<<<<<<<<<<<<<
+ *             self.buf = None
+ *             self.ptr = new LinearIndex(GlobalIndex(base), size)
+ */
+  __pyx_t_1 = (__pyx_v_perm == Py_None);
+  __pyx_t_2 = (__pyx_t_1 != 0);
+  if (__pyx_t_2) {
+
+    /* "pymusic.pyx":571
+ * 
+ *         if perm is None:
+ *             self.buf = None             # <<<<<<<<<<<<<<
+ *             self.ptr = new LinearIndex(GlobalIndex(base), size)
+ *         else:
+ */
+    __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(Py_None);
+    __Pyx_GOTREF(__pyx_v_self->buf);
+    __Pyx_DECREF(((PyObject *)__pyx_v_self->buf));
+    __pyx_v_self->buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)Py_None);
+
+    /* "pymusic.pyx":572
+ *         if perm is None:
+ *             self.buf = None
+ *             self.ptr = new LinearIndex(GlobalIndex(base), size)             # <<<<<<<<<<<<<<
+ *         else:
+ *             self.buf = Buffer(perm)
+ */
+    __pyx_v_self->ptr = new MUSIC::LinearIndex(MUSIC::GlobalIndex(__pyx_v_base), __pyx_v_size);
+    goto __pyx_L3;
+  }
+  /*else*/ {
+
+    /* "pymusic.pyx":574
+ *             self.ptr = new LinearIndex(GlobalIndex(base), size)
+ *         else:
+ *             self.buf = Buffer(perm)             # <<<<<<<<<<<<<<
+ *             if self.buf.dtype.size() != sizeof(int):
+ *                 arr = array('i', perm)
+ */
+    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 574; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_INCREF(__pyx_v_perm);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_perm);
+    __Pyx_GIVEREF(__pyx_v_perm);
+    __pyx_t_4 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_5music_8pybuffer_Buffer)), __pyx_t_3, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 574; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_GIVEREF(__pyx_t_4);
+    __Pyx_GOTREF(__pyx_v_self->buf);
+    __Pyx_DECREF(((PyObject *)__pyx_v_self->buf));
+    __pyx_v_self->buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)__pyx_t_4);
+    __pyx_t_4 = 0;
+
+    /* "pymusic.pyx":575
+ *         else:
+ *             self.buf = Buffer(perm)
+ *             if self.buf.dtype.size() != sizeof(int):             # <<<<<<<<<<<<<<
+ *                 arr = array('i', perm)
+ *                 self.buf = Buffer(arr)
+ */
+    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self->buf->dtype), __pyx_n_s_size); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_5 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && likely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    if (__pyx_t_5) {
+      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_5); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    } else {
+      __pyx_t_4 = __Pyx_PyObject_CallNoArg(__pyx_t_3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_3 = __Pyx_PyInt_FromSize_t((sizeof(int))); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_5 = PyObject_RichCompare(__pyx_t_4, __pyx_t_3, Py_NE); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (__pyx_t_2) {
+
+      /* "pymusic.pyx":576
+ *             self.buf = Buffer(perm)
+ *             if self.buf.dtype.size() != sizeof(int):
+ *                 arr = array('i', perm)             # <<<<<<<<<<<<<<
+ *                 self.buf = Buffer(arr)
+ *             self.ptr = new PermutationIndex(<GlobalIndex*>
+ */
+      __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_array); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 576; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_4 = NULL;
+      __pyx_t_6 = 0;
+      if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_3))) {
+        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+        if (likely(__pyx_t_4)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_4);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_3, function);
+          __pyx_t_6 = 1;
+        }
+      }
+      __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 576; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_7);
+      if (__pyx_t_4) {
+        PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_4); __Pyx_GIVEREF(__pyx_t_4); __pyx_t_4 = NULL;
+      }
+      __Pyx_INCREF(__pyx_n_s_i);
+      PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_n_s_i);
+      __Pyx_GIVEREF(__pyx_n_s_i);
+      __Pyx_INCREF(__pyx_v_perm);
+      PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, __pyx_v_perm);
+      __Pyx_GIVEREF(__pyx_v_perm);
+      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 576; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_7cpython_5array_array))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 576; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_v_arr = ((arrayobject *)__pyx_t_5);
+      __pyx_t_5 = 0;
+
+      /* "pymusic.pyx":577
+ *             if self.buf.dtype.size() != sizeof(int):
+ *                 arr = array('i', perm)
+ *                 self.buf = Buffer(arr)             # <<<<<<<<<<<<<<
+ *             self.ptr = new PermutationIndex(<GlobalIndex*>
+ *                                             self.buf.pybuf.buf,
+ */
+      __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 577; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_INCREF(((PyObject *)__pyx_v_arr));
+      PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_v_arr));
+      __Pyx_GIVEREF(((PyObject *)__pyx_v_arr));
+      __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_5music_8pybuffer_Buffer)), __pyx_t_5, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 577; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __Pyx_GIVEREF(__pyx_t_3);
+      __Pyx_GOTREF(__pyx_v_self->buf);
+      __Pyx_DECREF(((PyObject *)__pyx_v_self->buf));
+      __pyx_v_self->buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)__pyx_t_3);
+      __pyx_t_3 = 0;
+      goto __pyx_L4;
+    }
+    __pyx_L4:;
+
+    /* "pymusic.pyx":578
+ *                 arr = array('i', perm)
+ *                 self.buf = Buffer(arr)
+ *             self.ptr = new PermutationIndex(<GlobalIndex*>             # <<<<<<<<<<<<<<
+ *                                             self.buf.pybuf.buf,
+ *                                             self.buf.items)
+ */
+    __pyx_v_self->ptr = new MUSIC::PermutationIndex(((MUSIC::GlobalIndex *)__pyx_v_self->buf->pybuf.buf), __pyx_v_self->buf->items);
+  }
+  __pyx_L3:;
+
+  /* "pymusic.pyx":559
+ *     PermutationIndex: g = perm[l], where perm is an array
+ *     """
+ *     def __cinit__(self, object perm=None, int base=0, int size=-1):             # <<<<<<<<<<<<<<
+ *         """
+ *         Created internally
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("pymusic.IndexMap.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_arr);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":582
+ *                                             self.buf.items)
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         del self.ptr
+ * 
+ */
+
+/* Python wrapper */
+static void __pyx_pw_7pymusic_8IndexMap_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_7pymusic_8IndexMap_3__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_7pymusic_8IndexMap_2__dealloc__(((struct __pyx_obj_7pymusic_IndexMap *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+static void __pyx_pf_7pymusic_8IndexMap_2__dealloc__(struct __pyx_obj_7pymusic_IndexMap *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
+
+  /* "pymusic.pyx":583
+ * 
+ *     def __dealloc__(self):
+ *         del self.ptr             # <<<<<<<<<<<<<<
+ * 
+ * cdef class DataMap(object):
+ */
+  delete __pyx_v_self->ptr;
+
+  /* "pymusic.pyx":582
+ *                                             self.buf.items)
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         del self.ptr
+ * 
+ */
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "pymusic.pyx":591
+ *     IndexMap to construct a mapping for the Cont*Port transfers.
+ *     """
+ *     def __cinit__(self, Buffer buf, IndexMap index_map=None, int index=0):             # <<<<<<<<<<<<<<
+ *         """
+ *         Maps the Buffer of a data object between local and global indices.
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_7DataMap_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_7DataMap_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  struct __pyx_obj_5music_8pybuffer_Buffer *__pyx_v_buf = 0;
+  struct __pyx_obj_7pymusic_IndexMap *__pyx_v_index_map = 0;
+  int __pyx_v_index;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_buf,&__pyx_n_s_index_map,&__pyx_n_s_index,0};
+    PyObject* values[3] = {0,0,0};
+    values[1] = (PyObject *)((struct __pyx_obj_7pymusic_IndexMap *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_buf)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_index_map);
+          if (value) { values[1] = value; kw_args--; }
+        }
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_index);
+          if (value) { values[2] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 591; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)values[0]);
+    __pyx_v_index_map = ((struct __pyx_obj_7pymusic_IndexMap *)values[1]);
+    if (values[2]) {
+      __pyx_v_index = __Pyx_PyInt_As_int(values[2]); if (unlikely((__pyx_v_index == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 591; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    } else {
+      __pyx_v_index = ((int)0);
+    }
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 1, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 591; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.DataMap.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_buf), __pyx_ptype_5music_8pybuffer_Buffer, 1, "buf", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 591; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_index_map), __pyx_ptype_7pymusic_IndexMap, 1, "index_map", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 591; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_7pymusic_7DataMap___cinit__(((struct __pyx_obj_7pymusic_DataMap *)__pyx_v_self), __pyx_v_buf, __pyx_v_index_map, __pyx_v_index);
+
+  /* function exit code */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_7DataMap___cinit__(struct __pyx_obj_7pymusic_DataMap *__pyx_v_self, struct __pyx_obj_5music_8pybuffer_Buffer *__pyx_v_buf, struct __pyx_obj_7pymusic_IndexMap *__pyx_v_index_map, int __pyx_v_index) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  MUSIC::ArrayData *__pyx_t_1;
+  int __pyx_t_2;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":599
+ *                    a linear index
+ *         """
+ *         self.buf = buf             # <<<<<<<<<<<<<<
+ *         self.ptr = new CArrayData(buf.pybuf.buf,
+ *                                   buf.dtype.ob_mpi,
+ */
+  __Pyx_INCREF(((PyObject *)__pyx_v_buf));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_buf));
+  __Pyx_GOTREF(__pyx_v_self->buf);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->buf));
+  __pyx_v_self->buf = __pyx_v_buf;
+
+  /* "pymusic.pyx":603
+ *                                   buf.dtype.ob_mpi,
+ *                                   index, buf.items) \
+ *                    if index_map is None else \             # <<<<<<<<<<<<<<
+ *                    new CArrayData(buf.pybuf.buf,
+ *                                   buf.dtype.ob_mpi,
+ */
+  __pyx_t_2 = (((PyObject *)__pyx_v_index_map) == Py_None);
+  if ((__pyx_t_2 != 0)) {
+
+    /* "pymusic.pyx":600
+ *         """
+ *         self.buf = buf
+ *         self.ptr = new CArrayData(buf.pybuf.buf,             # <<<<<<<<<<<<<<
+ *                                   buf.dtype.ob_mpi,
+ *                                   index, buf.items) \
+ */
+    __pyx_t_1 = new MUSIC::ArrayData(__pyx_v_buf->pybuf.buf, __pyx_v_buf->dtype->ob_mpi, __pyx_v_index, __pyx_v_buf->items);
+  } else {
+
+    /* "pymusic.pyx":604
+ *                                   index, buf.items) \
+ *                    if index_map is None else \
+ *                    new CArrayData(buf.pybuf.buf,             # <<<<<<<<<<<<<<
+ *                                   buf.dtype.ob_mpi,
+ *                                   index_map.ptr)
+ */
+    __pyx_t_1 = new MUSIC::ArrayData(__pyx_v_buf->pybuf.buf, __pyx_v_buf->dtype->ob_mpi, __pyx_v_index_map->ptr);
+  }
+
+  /* "pymusic.pyx":600
+ *         """
+ *         self.buf = buf
+ *         self.ptr = new CArrayData(buf.pybuf.buf,             # <<<<<<<<<<<<<<
+ *                                   buf.dtype.ob_mpi,
+ *                                   index, buf.items) \
+ */
+  __pyx_v_self->ptr = __pyx_t_1;
+
+  /* "pymusic.pyx":591
+ *     IndexMap to construct a mapping for the Cont*Port transfers.
+ *     """
+ *     def __cinit__(self, Buffer buf, IndexMap index_map=None, int index=0):             # <<<<<<<<<<<<<<
+ *         """
+ *         Maps the Buffer of a data object between local and global indices.
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":608
+ *                                   index_map.ptr)
+ * 
+ *     def __dealloc__(self): del self.ptr             # <<<<<<<<<<<<<<
+ * 
+ * cdef class EventHandler:
+ */
+
+/* Python wrapper */
+static void __pyx_pw_7pymusic_7DataMap_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_7pymusic_7DataMap_3__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_7pymusic_7DataMap_2__dealloc__(((struct __pyx_obj_7pymusic_DataMap *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+static void __pyx_pf_7pymusic_7DataMap_2__dealloc__(struct __pyx_obj_7pymusic_DataMap *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
+  delete __pyx_v_self->ptr;
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "pymusic.pyx":616
+ *     or local EventHandler object for EventInputPort
+ *     """
+ *     def __cinit__(self, object func, IndexType t):             # <<<<<<<<<<<<<<
+ *         """
+ *         func: a callable of the form
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_12EventHandler_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_12EventHandler_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_func = 0;
+  MUSIC::Index::Type __pyx_v_t;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_func,&__pyx_n_s_t,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_func)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_t)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 616; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 616; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_func = values[0];
+    __pyx_v_t = ((MUSIC::Index::Type)PyInt_AsLong(values[1])); if (unlikely(PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 616; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 616; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.EventHandler.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_12EventHandler___cinit__(((struct __pyx_obj_7pymusic_EventHandler *)__pyx_v_self), __pyx_v_func, __pyx_v_t);
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_12EventHandler___cinit__(struct __pyx_obj_7pymusic_EventHandler *__pyx_v_self, PyObject *__pyx_v_func, MUSIC::Index::Type __pyx_v_t) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  MUSIC::EventHandler *__pyx_t_1;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":629
+ *         self.ptr = <CEventHandler*>                \
+ *                    new CEHGlobal(<PyObject*>func) \
+ *                    if t == IndexGLOBAL else       \             # <<<<<<<<<<<<<<
+ *                    <CEventHandler*>               \
+ *                    new CEHLocal(<PyObject*>func)
+ */
+  if (((__pyx_v_t == MUSIC::Index::GLOBAL) != 0)) {
+
+    /* "pymusic.pyx":627
+ *               to generalize func like this??)
+ *         """
+ *         self.ptr = <CEventHandler*>                \             # <<<<<<<<<<<<<<
+ *                    new CEHGlobal(<PyObject*>func) \
+ *                    if t == IndexGLOBAL else       \
+ */
+    __pyx_t_1 = ((MUSIC::EventHandler *)new MUSIC::EHGlobal(((PyObject *)__pyx_v_func)));
+  } else {
+
+    /* "pymusic.pyx":630
+ *                    new CEHGlobal(<PyObject*>func) \
+ *                    if t == IndexGLOBAL else       \
+ *                    <CEventHandler*>               \             # <<<<<<<<<<<<<<
+ *                    new CEHLocal(<PyObject*>func)
+ *         self.func = func
+ */
+    __pyx_t_1 = ((MUSIC::EventHandler *)new MUSIC::EHLocal(((PyObject *)__pyx_v_func)));
+  }
+
+  /* "pymusic.pyx":627
+ *               to generalize func like this??)
+ *         """
+ *         self.ptr = <CEventHandler*>                \             # <<<<<<<<<<<<<<
+ *                    new CEHGlobal(<PyObject*>func) \
+ *                    if t == IndexGLOBAL else       \
+ */
+  __pyx_v_self->ptr = __pyx_t_1;
+
+  /* "pymusic.pyx":632
+ *                    <CEventHandler*>               \
+ *                    new CEHLocal(<PyObject*>func)
+ *         self.func = func             # <<<<<<<<<<<<<<
+ * 
+ *     def __dealloc__(self): del self.ptr
+ */
+  __Pyx_INCREF(__pyx_v_func);
+  __Pyx_GIVEREF(__pyx_v_func);
+  __Pyx_GOTREF(__pyx_v_self->func);
+  __Pyx_DECREF(__pyx_v_self->func);
+  __pyx_v_self->func = __pyx_v_func;
+
+  /* "pymusic.pyx":616
+ *     or local EventHandler object for EventInputPort
+ *     """
+ *     def __cinit__(self, object func, IndexType t):             # <<<<<<<<<<<<<<
+ *         """
+ *         func: a callable of the form
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":634
+ *         self.func = func
+ * 
+ *     def __dealloc__(self): del self.ptr             # <<<<<<<<<<<<<<
+ * 
+ * cdef class _Index:
+ */
+
+/* Python wrapper */
+static void __pyx_pw_7pymusic_12EventHandler_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_7pymusic_12EventHandler_3__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_7pymusic_12EventHandler_2__dealloc__(((struct __pyx_obj_7pymusic_EventHandler *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+static void __pyx_pf_7pymusic_12EventHandler_2__dealloc__(struct __pyx_obj_7pymusic_EventHandler *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
+  delete __pyx_v_self->ptr;
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "pymusic.pyx":648
+ *     cdef readonly dict backmap
+ * 
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         """ SINGLETON """
+ *         self.GLOBAL = IndexGLOBAL
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_6_Index_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_6_Index_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) {
+    __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;}
+  if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__cinit__", 0))) return -1;
+  __pyx_r = __pyx_pf_7pymusic_6_Index___cinit__(((struct __pyx_obj_7pymusic__Index *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_6_Index___cinit__(struct __pyx_obj_7pymusic__Index *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":650
+ *     def __cinit__(self):
+ *         """ SINGLETON """
+ *         self.GLOBAL = IndexGLOBAL             # <<<<<<<<<<<<<<
+ *         self.LOCAL = IndexLOCAL
+ *         self.backmap = {
+ */
+  __pyx_v_self->GLOBAL = MUSIC::Index::GLOBAL;
+
+  /* "pymusic.pyx":651
+ *         """ SINGLETON """
+ *         self.GLOBAL = IndexGLOBAL
+ *         self.LOCAL = IndexLOCAL             # <<<<<<<<<<<<<<
+ *         self.backmap = {
+ *             IndexGLOBAL: "GLOBAL",
+ */
+  __pyx_v_self->LOCAL = MUSIC::Index::LOCAL;
+
+  /* "pymusic.pyx":652
+ *         self.GLOBAL = IndexGLOBAL
+ *         self.LOCAL = IndexLOCAL
+ *         self.backmap = {             # <<<<<<<<<<<<<<
+ *             IndexGLOBAL: "GLOBAL",
+ *             IndexLOCAL: "LOCAL"
+ */
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 652; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+
+  /* "pymusic.pyx":653
+ *         self.LOCAL = IndexLOCAL
+ *         self.backmap = {
+ *             IndexGLOBAL: "GLOBAL",             # <<<<<<<<<<<<<<
+ *             IndexLOCAL: "LOCAL"
+ *         };
+ */
+  __pyx_t_2 = PyInt_FromLong(MUSIC::Index::GLOBAL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 653; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_t_1, __pyx_t_2, __pyx_n_s_GLOBAL) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 652; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":654
+ *         self.backmap = {
+ *             IndexGLOBAL: "GLOBAL",
+ *             IndexLOCAL: "LOCAL"             # <<<<<<<<<<<<<<
+ *         };
+ * 
+ */
+  __pyx_t_2 = PyInt_FromLong(MUSIC::Index::LOCAL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 654; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_t_1, __pyx_t_2, __pyx_n_s_LOCAL) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 652; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":652
+ *         self.GLOBAL = IndexGLOBAL
+ *         self.LOCAL = IndexLOCAL
+ *         self.backmap = {             # <<<<<<<<<<<<<<
+ *             IndexGLOBAL: "GLOBAL",
+ *             IndexLOCAL: "LOCAL"
+ */
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->backmap);
+  __Pyx_DECREF(__pyx_v_self->backmap);
+  __pyx_v_self->backmap = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":648
+ *     cdef readonly dict backmap
+ * 
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         """ SINGLETON """
+ *         self.GLOBAL = IndexGLOBAL
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("pymusic._Index.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":657
+ *         };
+ * 
+ *     def tostr(self, int index):             # <<<<<<<<<<<<<<
+ *         """" tostring(Index.{GLOBAL,LOCAL}) --> "{GLOBAL,LOCAL}" """
+ *         return self.backmap[index]
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_6_Index_3tostr(PyObject *__pyx_v_self, PyObject *__pyx_arg_index); /*proto*/
+static char __pyx_doc_7pymusic_6_Index_2tostr[] = "\" tostring(Index.{GLOBAL,LOCAL}) --> \"{GLOBAL,LOCAL}\" ";
+static PyObject *__pyx_pw_7pymusic_6_Index_3tostr(PyObject *__pyx_v_self, PyObject *__pyx_arg_index) {
+  int __pyx_v_index;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("tostr (wrapper)", 0);
+  assert(__pyx_arg_index); {
+    __pyx_v_index = __Pyx_PyInt_As_int(__pyx_arg_index); if (unlikely((__pyx_v_index == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 657; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic._Index.tostr", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_6_Index_2tostr(((struct __pyx_obj_7pymusic__Index *)__pyx_v_self), ((int)__pyx_v_index));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_6_Index_2tostr(struct __pyx_obj_7pymusic__Index *__pyx_v_self, int __pyx_v_index) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("tostr", 0);
+
+  /* "pymusic.pyx":659
+ *     def tostr(self, int index):
+ *         """" tostring(Index.{GLOBAL,LOCAL}) --> "{GLOBAL,LOCAL}" """
+ *         return self.backmap[index]             # <<<<<<<<<<<<<<
+ * 
+ * # And here is the singleton def
+ */
+  __Pyx_XDECREF(__pyx_r);
+  if (unlikely(__pyx_v_self->backmap == Py_None)) {
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
+    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 659; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_index); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 659; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_self->backmap, __pyx_t_1); if (unlikely(__pyx_t_2 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 659; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_r = __pyx_t_2;
+  __pyx_t_2 = 0;
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":657
+ *         };
+ * 
+ *     def tostr(self, int index):             # <<<<<<<<<<<<<<
+ *         """" tostring(Index.{GLOBAL,LOCAL}) --> "{GLOBAL,LOCAL}" """
+ *         return self.backmap[index]
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("pymusic._Index.tostr", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":644
+ *     purposes
+ *     """
+ *     cdef readonly int GLOBAL             # <<<<<<<<<<<<<<
+ *     cdef readonly int LOCAL
+ *     cdef readonly dict backmap
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_6_Index_6GLOBAL_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_7pymusic_6_Index_6GLOBAL_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_6_Index_6GLOBAL___get__(((struct __pyx_obj_7pymusic__Index *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_6_Index_6GLOBAL___get__(struct __pyx_obj_7pymusic__Index *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->GLOBAL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 644; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic._Index.GLOBAL.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":645
+ *     """
+ *     cdef readonly int GLOBAL
+ *     cdef readonly int LOCAL             # <<<<<<<<<<<<<<
+ *     cdef readonly dict backmap
+ * 
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_6_Index_5LOCAL_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_7pymusic_6_Index_5LOCAL_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_6_Index_5LOCAL___get__(((struct __pyx_obj_7pymusic__Index *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_6_Index_5LOCAL___get__(struct __pyx_obj_7pymusic__Index *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->LOCAL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 645; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("pymusic._Index.LOCAL.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":646
+ *     cdef readonly int GLOBAL
+ *     cdef readonly int LOCAL
+ *     cdef readonly dict backmap             # <<<<<<<<<<<<<<
+ * 
+ *     def __cinit__(self):
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_7pymusic_6_Index_7backmap_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_7pymusic_6_Index_7backmap_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_7pymusic_6_Index_7backmap___get__(((struct __pyx_obj_7pymusic__Index *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_7pymusic_6_Index_7backmap___get__(struct __pyx_obj_7pymusic__Index *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_self->backmap);
+  __pyx_r = __pyx_v_self->backmap;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":664
+ * Index = _Index()
+ * 
+ * cdef cbool EventCallback(PyObject* func,             # <<<<<<<<<<<<<<
+ *                          double d,
+ *                          IndexType t,
+ */
+
+bool MUSIC::EventCallback(PyObject *__pyx_v_func, double __pyx_v_d, MUSIC::Index::Type __pyx_v_t, int __pyx_v_i) {
+  bool __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  Py_ssize_t __pyx_t_7;
+  PyObject *__pyx_t_8 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("EventCallback", 0);
+
+  /* "pymusic.pyx":676
+ *     int i: index of event
+ *     """
+ *     (<object>func)(d, t, i)             # <<<<<<<<<<<<<<
+ *     return True
+ * 
+ */
+  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_d); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyInt_FromLong(__pyx_v_t); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_INCREF(((PyObject *)__pyx_v_func));
+  __pyx_t_5 = ((PyObject *)__pyx_v_func); __pyx_t_6 = NULL;
+  __pyx_t_7 = 0;
+  if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_5))) {
+    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+    if (likely(__pyx_t_6)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+      __Pyx_INCREF(__pyx_t_6);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_5, function);
+      __pyx_t_7 = 1;
+    }
+  }
+  __pyx_t_8 = PyTuple_New(3+__pyx_t_7); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_8);
+  if (__pyx_t_6) {
+    PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __Pyx_GIVEREF(__pyx_t_6); __pyx_t_6 = NULL;
+  }
+  PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_t_3);
+  __Pyx_GIVEREF(__pyx_t_3);
+  PyTuple_SET_ITEM(__pyx_t_8, 2+__pyx_t_7, __pyx_t_4);
+  __Pyx_GIVEREF(__pyx_t_4);
+  __pyx_t_2 = 0;
+  __pyx_t_3 = 0;
+  __pyx_t_4 = 0;
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 676; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":677
+ *     """
+ *     (<object>func)(d, t, i)
+ *     return True             # <<<<<<<<<<<<<<
+ * 
+ * cdef class MessageHandler:
+ */
+  __pyx_r = 1;
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":664
+ * Index = _Index()
+ * 
+ * cdef cbool EventCallback(PyObject* func,             # <<<<<<<<<<<<<<
+ *                          double d,
+ *                          IndexType t,
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_AddTraceback("pymusic.EventCallback", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":685
+ *     It may (or may not) depickle messages
+ *     """
+ *     def __cinit__(self, object func, bint pickled):             # <<<<<<<<<<<<<<
+ *         """
+ *         func: The function to be called on a message, of the form
+ */
+
+/* Python wrapper */
+static int __pyx_pw_7pymusic_14MessageHandler_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_7pymusic_14MessageHandler_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_func = 0;
+  int __pyx_v_pickled;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_func,&__pyx_n_s_pickled,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_func)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_pickled)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 2, 2, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 685; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 685; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_func = values[0];
+    __pyx_v_pickled = __Pyx_PyObject_IsTrue(values[1]); if (unlikely((__pyx_v_pickled == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 685; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 685; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("pymusic.MessageHandler.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_7pymusic_14MessageHandler___cinit__(((struct __pyx_obj_7pymusic_MessageHandler *)__pyx_v_self), __pyx_v_func, __pyx_v_pickled);
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7pymusic_14MessageHandler___cinit__(struct __pyx_obj_7pymusic_MessageHandler *__pyx_v_self, PyObject *__pyx_v_func, int __pyx_v_pickled) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__cinit__", 0);
+
+  /* "pymusic.pyx":693
+ *         pickled: if true, the msg needs to be depickled
+ *         """
+ *         self.ptr = new CMHandler(<PyObject*>func, pickled)             # <<<<<<<<<<<<<<
+ *         self.func = func
+ * 
+ */
+  __pyx_v_self->ptr = new MUSIC::MHandler(((PyObject *)__pyx_v_func), __pyx_v_pickled);
+
+  /* "pymusic.pyx":694
+ *         """
+ *         self.ptr = new CMHandler(<PyObject*>func, pickled)
+ *         self.func = func             # <<<<<<<<<<<<<<
+ * 
+ *     def __dealloc__(self):  del self.ptr
+ */
+  __Pyx_INCREF(__pyx_v_func);
+  __Pyx_GIVEREF(__pyx_v_func);
+  __Pyx_GOTREF(__pyx_v_self->func);
+  __Pyx_DECREF(__pyx_v_self->func);
+  __pyx_v_self->func = __pyx_v_func;
+
+  /* "pymusic.pyx":685
+ *     It may (or may not) depickle messages
+ *     """
+ *     def __cinit__(self, object func, bint pickled):             # <<<<<<<<<<<<<<
+ *         """
+ *         func: The function to be called on a message, of the form
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "pymusic.pyx":696
+ *         self.func = func
+ * 
+ *     def __dealloc__(self):  del self.ptr             # <<<<<<<<<<<<<<
+ * 
+ * cdef cbool MessageCallback(PyObject* func,
+ */
+
+/* Python wrapper */
+static void __pyx_pw_7pymusic_14MessageHandler_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_7pymusic_14MessageHandler_3__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_7pymusic_14MessageHandler_2__dealloc__(((struct __pyx_obj_7pymusic_MessageHandler *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+static void __pyx_pf_7pymusic_14MessageHandler_2__dealloc__(struct __pyx_obj_7pymusic_MessageHandler *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
+  delete __pyx_v_self->ptr;
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "pymusic.pyx":698
+ *     def __dealloc__(self):  del self.ptr
+ * 
+ * cdef cbool MessageCallback(PyObject* func,             # <<<<<<<<<<<<<<
+ *                            double t,
+ *                            void* msg,
+ */
+
+bool MUSIC::MessageCallback(PyObject *__pyx_v_func, double __pyx_v_t, void *__pyx_v_msg, size_t __pyx_v_s, bool __pyx_v_pickled) {
+  PyObject *__pyx_v_pobj = 0;
+  PyObject *__pyx_v_obj = 0;
+  bool __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  Py_ssize_t __pyx_t_6;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("MessageCallback", 0);
+
+  /* "pymusic.pyx":712
+ *               or simply a bytearray of data (you figure out the source)
+ *     """
+ *     cdef str pobj = (<char*>msg)[:s]             # <<<<<<<<<<<<<<
+ *     cdef object obj = pickle.loads(pobj) if pickled else <bytearray> pobj
+ *     (<object>func)(t, obj)
+ */
+  __pyx_t_1 = __Pyx_PyStr_FromStringAndSize(((char *)__pyx_v_msg) + 0, __pyx_v_s - 0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 712; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_pobj = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":713
+ *     """
+ *     cdef str pobj = (<char*>msg)[:s]
+ *     cdef object obj = pickle.loads(pobj) if pickled else <bytearray> pobj             # <<<<<<<<<<<<<<
+ *     (<object>func)(t, obj)
+ *     return True
+ */
+  if ((__pyx_v_pickled != 0)) {
+    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_pickle); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 713; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_loads); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 713; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_3 = NULL;
+    if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_3)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    if (!__pyx_t_3) {
+      __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_pobj); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 713; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+    } else {
+      __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 713; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3); __Pyx_GIVEREF(__pyx_t_3); __pyx_t_3 = NULL;
+      __Pyx_INCREF(__pyx_v_pobj);
+      PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_v_pobj);
+      __Pyx_GIVEREF(__pyx_v_pobj);
+      __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_5, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 713; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    }
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __pyx_t_1 = __pyx_t_2;
+    __pyx_t_2 = 0;
+  } else {
+    __Pyx_INCREF(((PyObject*)__pyx_v_pobj));
+    __pyx_t_1 = __pyx_v_pobj;
+  }
+  __pyx_v_obj = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":714
+ *     cdef str pobj = (<char*>msg)[:s]
+ *     cdef object obj = pickle.loads(pobj) if pickled else <bytearray> pobj
+ *     (<object>func)(t, obj)             # <<<<<<<<<<<<<<
+ *     return True
+ * 
+ */
+  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_t); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 714; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(((PyObject *)__pyx_v_func));
+  __pyx_t_4 = ((PyObject *)__pyx_v_func); __pyx_t_5 = NULL;
+  __pyx_t_6 = 0;
+  if (CYTHON_COMPILING_IN_CPYTHON && unlikely(PyMethod_Check(__pyx_t_4))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_4, function);
+      __pyx_t_6 = 1;
+    }
+  }
+  __pyx_t_3 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 714; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  if (__pyx_t_5) {
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5); __Pyx_GIVEREF(__pyx_t_5); __pyx_t_5 = NULL;
+  }
+  PyTuple_SET_ITEM(__pyx_t_3, 0+__pyx_t_6, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __Pyx_INCREF(__pyx_v_obj);
+  PyTuple_SET_ITEM(__pyx_t_3, 1+__pyx_t_6, __pyx_v_obj);
+  __Pyx_GIVEREF(__pyx_v_obj);
+  __pyx_t_2 = 0;
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 714; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":715
+ *     cdef object obj = pickle.loads(pobj) if pickled else <bytearray> pobj
+ *     (<object>func)(t, obj)
+ *     return True             # <<<<<<<<<<<<<<
+ * 
+ * #############################################################################
+ */
+  __pyx_r = 1;
+  goto __pyx_L0;
+
+  /* "pymusic.pyx":698
+ *     def __dealloc__(self):  del self.ptr
+ * 
+ * cdef cbool MessageCallback(PyObject* func,             # <<<<<<<<<<<<<<
+ *                            double t,
+ *                            void* msg,
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("pymusic.MessageCallback", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_pobj);
+  __Pyx_XDECREF(__pyx_v_obj);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "array.pxd":91
+ *             __data_union data
+ * 
+ *         def __getbuffer__(self, Py_buffer* info, int flags):             # <<<<<<<<<<<<<<
+ *             # This implementation of getbuffer is geared towards Cython
+ *             # requirements, and does not yet fullfill the PEP.
+ */
+
+/* Python wrapper */
+static CYTHON_UNUSED int __pyx_pw_7cpython_5array_5array_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /*proto*/
+static CYTHON_UNUSED int __pyx_pw_7cpython_5array_5array_1__getbuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__getbuffer__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_7cpython_5array_5array___getbuffer__(((arrayobject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info), ((int)__pyx_v_flags));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_7cpython_5array_5array___getbuffer__(arrayobject *__pyx_v_self, Py_buffer *__pyx_v_info, CYTHON_UNUSED int __pyx_v_flags) {
+  PyObject *__pyx_v_item_count = NULL;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  char *__pyx_t_2;
+  int __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  Py_ssize_t __pyx_t_5;
+  int __pyx_t_6;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__getbuffer__", 0);
+  if (__pyx_v_info != NULL) {
+    __pyx_v_info->obj = Py_None; __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(__pyx_v_info->obj);
+  }
+
+  /* "array.pxd":96
+ *             # In particular strided access is always provided regardless
+ *             # of flags
+ *             item_count = Py_SIZE(self)             # <<<<<<<<<<<<<<
+ * 
+ *             info.suboffsets = NULL
+ */
+  __pyx_t_1 = PyInt_FromSsize_t(Py_SIZE(((PyObject *)__pyx_v_self))); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_item_count = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "array.pxd":98
+ *             item_count = Py_SIZE(self)
+ * 
+ *             info.suboffsets = NULL             # <<<<<<<<<<<<<<
+ *             info.buf = self.data.as_chars
+ *             info.readonly = 0
+ */
+  __pyx_v_info->suboffsets = NULL;
+
+  /* "array.pxd":99
+ * 
+ *             info.suboffsets = NULL
+ *             info.buf = self.data.as_chars             # <<<<<<<<<<<<<<
+ *             info.readonly = 0
+ *             info.ndim = 1
+ */
+  __pyx_t_2 = __pyx_v_self->data.as_chars;
+  __pyx_v_info->buf = __pyx_t_2;
+
+  /* "array.pxd":100
+ *             info.suboffsets = NULL
+ *             info.buf = self.data.as_chars
+ *             info.readonly = 0             # <<<<<<<<<<<<<<
+ *             info.ndim = 1
+ *             info.itemsize = self.ob_descr.itemsize   # e.g. sizeof(float)
+ */
+  __pyx_v_info->readonly = 0;
+
+  /* "array.pxd":101
+ *             info.buf = self.data.as_chars
+ *             info.readonly = 0
+ *             info.ndim = 1             # <<<<<<<<<<<<<<
+ *             info.itemsize = self.ob_descr.itemsize   # e.g. sizeof(float)
+ *             info.len = info.itemsize * item_count
+ */
+  __pyx_v_info->ndim = 1;
+
+  /* "array.pxd":102
+ *             info.readonly = 0
+ *             info.ndim = 1
+ *             info.itemsize = self.ob_descr.itemsize   # e.g. sizeof(float)             # <<<<<<<<<<<<<<
+ *             info.len = info.itemsize * item_count
+ * 
+ */
+  __pyx_t_3 = __pyx_v_self->ob_descr->itemsize;
+  __pyx_v_info->itemsize = __pyx_t_3;
+
+  /* "array.pxd":103
+ *             info.ndim = 1
+ *             info.itemsize = self.ob_descr.itemsize   # e.g. sizeof(float)
+ *             info.len = info.itemsize * item_count             # <<<<<<<<<<<<<<
+ * 
+ *             info.shape = <Py_ssize_t*> PyMem_Malloc(sizeof(Py_ssize_t) + 2)
+ */
+  __pyx_t_1 = PyInt_FromSsize_t(__pyx_v_info->itemsize); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_4 = PyNumber_Multiply(__pyx_t_1, __pyx_v_item_count); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_5 = __Pyx_PyIndex_AsSsize_t(__pyx_t_4); if (unlikely((__pyx_t_5 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_v_info->len = __pyx_t_5;
+
+  /* "array.pxd":105
+ *             info.len = info.itemsize * item_count
+ * 
+ *             info.shape = <Py_ssize_t*> PyMem_Malloc(sizeof(Py_ssize_t) + 2)             # <<<<<<<<<<<<<<
+ *             if not info.shape:
+ *                 raise MemoryError()
+ */
+  __pyx_v_info->shape = ((Py_ssize_t *)PyMem_Malloc(((sizeof(Py_ssize_t)) + 2)));
+
+  /* "array.pxd":106
+ * 
+ *             info.shape = <Py_ssize_t*> PyMem_Malloc(sizeof(Py_ssize_t) + 2)
+ *             if not info.shape:             # <<<<<<<<<<<<<<
+ *                 raise MemoryError()
+ *             info.shape[0] = item_count      # constant regardless of resizing
+ */
+  __pyx_t_6 = ((!(__pyx_v_info->shape != 0)) != 0);
+  if (__pyx_t_6) {
+
+    /* "array.pxd":107
+ *             info.shape = <Py_ssize_t*> PyMem_Malloc(sizeof(Py_ssize_t) + 2)
+ *             if not info.shape:
+ *                 raise MemoryError()             # <<<<<<<<<<<<<<
+ *             info.shape[0] = item_count      # constant regardless of resizing
+ *             info.strides = &info.itemsize
+ */
+    PyErr_NoMemory(); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+
+  /* "array.pxd":108
+ *             if not info.shape:
+ *                 raise MemoryError()
+ *             info.shape[0] = item_count      # constant regardless of resizing             # <<<<<<<<<<<<<<
+ *             info.strides = &info.itemsize
+ * 
+ */
+  __pyx_t_5 = __Pyx_PyIndex_AsSsize_t(__pyx_v_item_count); if (unlikely((__pyx_t_5 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  (__pyx_v_info->shape[0]) = __pyx_t_5;
+
+  /* "array.pxd":109
+ *                 raise MemoryError()
+ *             info.shape[0] = item_count      # constant regardless of resizing
+ *             info.strides = &info.itemsize             # <<<<<<<<<<<<<<
+ * 
+ *             info.format = <char*> (info.shape + 1)
+ */
+  __pyx_v_info->strides = (&__pyx_v_info->itemsize);
+
+  /* "array.pxd":111
+ *             info.strides = &info.itemsize
+ * 
+ *             info.format = <char*> (info.shape + 1)             # <<<<<<<<<<<<<<
+ *             info.format[0] = self.ob_descr.typecode
+ *             info.format[1] = 0
+ */
+  __pyx_v_info->format = ((char *)(__pyx_v_info->shape + 1));
+
+  /* "array.pxd":112
+ * 
+ *             info.format = <char*> (info.shape + 1)
+ *             info.format[0] = self.ob_descr.typecode             # <<<<<<<<<<<<<<
+ *             info.format[1] = 0
+ *             info.obj = self
+ */
+  __pyx_t_3 = __pyx_v_self->ob_descr->typecode;
+  (__pyx_v_info->format[0]) = __pyx_t_3;
+
+  /* "array.pxd":113
+ *             info.format = <char*> (info.shape + 1)
+ *             info.format[0] = self.ob_descr.typecode
+ *             info.format[1] = 0             # <<<<<<<<<<<<<<
+ *             info.obj = self
+ * 
+ */
+  (__pyx_v_info->format[1]) = 0;
+
+  /* "array.pxd":114
+ *             info.format[0] = self.ob_descr.typecode
+ *             info.format[1] = 0
+ *             info.obj = self             # <<<<<<<<<<<<<<
+ * 
+ *         def __releasebuffer__(self, Py_buffer* info):
+ */
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+  __Pyx_GOTREF(__pyx_v_info->obj);
+  __Pyx_DECREF(__pyx_v_info->obj);
+  __pyx_v_info->obj = ((PyObject *)__pyx_v_self);
+
+  /* "array.pxd":91
+ *             __data_union data
+ * 
+ *         def __getbuffer__(self, Py_buffer* info, int flags):             # <<<<<<<<<<<<<<
+ *             # This implementation of getbuffer is geared towards Cython
+ *             # requirements, and does not yet fullfill the PEP.
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("cpython.array.array.__getbuffer__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  if (__pyx_v_info != NULL && __pyx_v_info->obj != NULL) {
+    __Pyx_GOTREF(__pyx_v_info->obj);
+    __Pyx_DECREF(__pyx_v_info->obj); __pyx_v_info->obj = NULL;
+  }
+  goto __pyx_L2;
+  __pyx_L0:;
+  if (__pyx_v_info != NULL && __pyx_v_info->obj == Py_None) {
+    __Pyx_GOTREF(Py_None);
+    __Pyx_DECREF(Py_None); __pyx_v_info->obj = NULL;
+  }
+  __pyx_L2:;
+  __Pyx_XDECREF(__pyx_v_item_count);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "array.pxd":116
+ *             info.obj = self
+ * 
+ *         def __releasebuffer__(self, Py_buffer* info):             # <<<<<<<<<<<<<<
+ *             PyMem_Free(info.shape)
+ * 
+ */
+
+/* Python wrapper */
+static CYTHON_UNUSED void __pyx_pw_7cpython_5array_5array_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info); /*proto*/
+static CYTHON_UNUSED void __pyx_pw_7cpython_5array_5array_3__releasebuffer__(PyObject *__pyx_v_self, Py_buffer *__pyx_v_info) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__releasebuffer__ (wrapper)", 0);
+  __pyx_pf_7cpython_5array_5array_2__releasebuffer__(((arrayobject *)__pyx_v_self), ((Py_buffer *)__pyx_v_info));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+static void __pyx_pf_7cpython_5array_5array_2__releasebuffer__(CYTHON_UNUSED arrayobject *__pyx_v_self, Py_buffer *__pyx_v_info) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__releasebuffer__", 0);
+
+  /* "array.pxd":117
+ * 
+ *         def __releasebuffer__(self, Py_buffer* info):
+ *             PyMem_Free(info.shape)             # <<<<<<<<<<<<<<
+ * 
+ *     array newarrayobject(PyTypeObject* type, Py_ssize_t size, arraydescr *descr)
+ */
+  PyMem_Free(__pyx_v_info->shape);
+
+  /* "array.pxd":116
+ *             info.obj = self
+ * 
+ *         def __releasebuffer__(self, Py_buffer* info):             # <<<<<<<<<<<<<<
+ *             PyMem_Free(info.shape)
+ * 
+ */
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "array.pxd":128
+ * 
+ * 
+ * cdef inline array clone(array template, Py_ssize_t length, bint zero):             # <<<<<<<<<<<<<<
+ *     """ fast creation of a new array, given a template array.
+ *     type will be same as template.
+ */
+
+static CYTHON_INLINE arrayobject *__pyx_f_7cpython_5array_clone(arrayobject *__pyx_v_template, Py_ssize_t __pyx_v_length, int __pyx_v_zero) {
+  arrayobject *__pyx_v_op = NULL;
+  arrayobject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_t_3;
+  int __pyx_t_4;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("clone", 0);
+
+  /* "array.pxd":132
+ *     type will be same as template.
+ *     if zero is true, new array will be initialized with zeroes."""
+ *     op = newarrayobject(Py_TYPE(template), length, template.ob_descr)             # <<<<<<<<<<<<<<
+ *     if zero and op is not None:
+ *         memset(op.data.as_chars, 0, length * op.ob_descr.itemsize)
+ */
+  __pyx_t_1 = ((PyObject *)newarrayobject(Py_TYPE(((PyObject *)__pyx_v_template)), __pyx_v_length, __pyx_v_template->ob_descr)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_op = ((arrayobject *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "array.pxd":133
+ *     if zero is true, new array will be initialized with zeroes."""
+ *     op = newarrayobject(Py_TYPE(template), length, template.ob_descr)
+ *     if zero and op is not None:             # <<<<<<<<<<<<<<
+ *         memset(op.data.as_chars, 0, length * op.ob_descr.itemsize)
+ *     return op
+ */
+  __pyx_t_3 = (__pyx_v_zero != 0);
+  if (__pyx_t_3) {
+  } else {
+    __pyx_t_2 = __pyx_t_3;
+    goto __pyx_L4_bool_binop_done;
+  }
+  __pyx_t_3 = (((PyObject *)__pyx_v_op) != Py_None);
+  __pyx_t_4 = (__pyx_t_3 != 0);
+  __pyx_t_2 = __pyx_t_4;
+  __pyx_L4_bool_binop_done:;
+  if (__pyx_t_2) {
+
+    /* "array.pxd":134
+ *     op = newarrayobject(Py_TYPE(template), length, template.ob_descr)
+ *     if zero and op is not None:
+ *         memset(op.data.as_chars, 0, length * op.ob_descr.itemsize)             # <<<<<<<<<<<<<<
+ *     return op
+ * 
+ */
+    memset(__pyx_v_op->data.as_chars, 0, (__pyx_v_length * __pyx_v_op->ob_descr->itemsize));
+    goto __pyx_L3;
+  }
+  __pyx_L3:;
+
+  /* "array.pxd":135
+ *     if zero and op is not None:
+ *         memset(op.data.as_chars, 0, length * op.ob_descr.itemsize)
+ *     return op             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline array copy(array self):
+ */
+  __Pyx_XDECREF(((PyObject *)__pyx_r));
+  __Pyx_INCREF(((PyObject *)__pyx_v_op));
+  __pyx_r = __pyx_v_op;
+  goto __pyx_L0;
+
+  /* "array.pxd":128
+ * 
+ * 
+ * cdef inline array clone(array template, Py_ssize_t length, bint zero):             # <<<<<<<<<<<<<<
+ *     """ fast creation of a new array, given a template array.
+ *     type will be same as template.
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("cpython.array.clone", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_op);
+  __Pyx_XGIVEREF((PyObject *)__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "array.pxd":137
+ *     return op
+ * 
+ * cdef inline array copy(array self):             # <<<<<<<<<<<<<<
+ *     """ make a copy of an array. """
+ *     op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr)
+ */
+
+static CYTHON_INLINE arrayobject *__pyx_f_7cpython_5array_copy(arrayobject *__pyx_v_self) {
+  arrayobject *__pyx_v_op = NULL;
+  arrayobject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("copy", 0);
+
+  /* "array.pxd":139
+ * cdef inline array copy(array self):
+ *     """ make a copy of an array. """
+ *     op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr)             # <<<<<<<<<<<<<<
+ *     memcpy(op.data.as_chars, self.data.as_chars, Py_SIZE(op) * op.ob_descr.itemsize)
+ *     return op
+ */
+  __pyx_t_1 = ((PyObject *)newarrayobject(Py_TYPE(((PyObject *)__pyx_v_self)), Py_SIZE(((PyObject *)__pyx_v_self)), __pyx_v_self->ob_descr)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_op = ((arrayobject *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "array.pxd":140
+ *     """ make a copy of an array. """
+ *     op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr)
+ *     memcpy(op.data.as_chars, self.data.as_chars, Py_SIZE(op) * op.ob_descr.itemsize)             # <<<<<<<<<<<<<<
+ *     return op
+ * 
+ */
+  memcpy(__pyx_v_op->data.as_chars, __pyx_v_self->data.as_chars, (Py_SIZE(((PyObject *)__pyx_v_op)) * __pyx_v_op->ob_descr->itemsize));
+
+  /* "array.pxd":141
+ *     op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr)
+ *     memcpy(op.data.as_chars, self.data.as_chars, Py_SIZE(op) * op.ob_descr.itemsize)
+ *     return op             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline int extend_buffer(array self, char* stuff, Py_ssize_t n) except -1:
+ */
+  __Pyx_XDECREF(((PyObject *)__pyx_r));
+  __Pyx_INCREF(((PyObject *)__pyx_v_op));
+  __pyx_r = __pyx_v_op;
+  goto __pyx_L0;
+
+  /* "array.pxd":137
+ *     return op
+ * 
+ * cdef inline array copy(array self):             # <<<<<<<<<<<<<<
+ *     """ make a copy of an array. """
+ *     op = newarrayobject(Py_TYPE(self), Py_SIZE(self), self.ob_descr)
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("cpython.array.copy", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_op);
+  __Pyx_XGIVEREF((PyObject *)__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "array.pxd":143
+ *     return op
+ * 
+ * cdef inline int extend_buffer(array self, char* stuff, Py_ssize_t n) except -1:             # <<<<<<<<<<<<<<
+ *     """ efficent appending of new stuff of same type
+ *     (e.g. of same array type)
+ */
+
+static CYTHON_INLINE int __pyx_f_7cpython_5array_extend_buffer(arrayobject *__pyx_v_self, char *__pyx_v_stuff, Py_ssize_t __pyx_v_n) {
+  Py_ssize_t __pyx_v_itemsize;
+  Py_ssize_t __pyx_v_origsize;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("extend_buffer", 0);
+
+  /* "array.pxd":147
+ *     (e.g. of same array type)
+ *     n: number of elements (not number of bytes!) """
+ *     cdef Py_ssize_t itemsize = self.ob_descr.itemsize             # <<<<<<<<<<<<<<
+ *     cdef Py_ssize_t origsize = Py_SIZE(self)
+ *     resize_smart(self, origsize + n)
+ */
+  __pyx_t_1 = __pyx_v_self->ob_descr->itemsize;
+  __pyx_v_itemsize = __pyx_t_1;
+
+  /* "array.pxd":148
+ *     n: number of elements (not number of bytes!) """
+ *     cdef Py_ssize_t itemsize = self.ob_descr.itemsize
+ *     cdef Py_ssize_t origsize = Py_SIZE(self)             # <<<<<<<<<<<<<<
+ *     resize_smart(self, origsize + n)
+ *     memcpy(self.data.as_chars + origsize * itemsize, stuff, n * itemsize)
+ */
+  __pyx_v_origsize = Py_SIZE(((PyObject *)__pyx_v_self));
+
+  /* "array.pxd":149
+ *     cdef Py_ssize_t itemsize = self.ob_descr.itemsize
+ *     cdef Py_ssize_t origsize = Py_SIZE(self)
+ *     resize_smart(self, origsize + n)             # <<<<<<<<<<<<<<
+ *     memcpy(self.data.as_chars + origsize * itemsize, stuff, n * itemsize)
+ *     return 0
+ */
+  __pyx_t_1 = resize_smart(__pyx_v_self, (__pyx_v_origsize + __pyx_v_n)); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "array.pxd":150
+ *     cdef Py_ssize_t origsize = Py_SIZE(self)
+ *     resize_smart(self, origsize + n)
+ *     memcpy(self.data.as_chars + origsize * itemsize, stuff, n * itemsize)             # <<<<<<<<<<<<<<
+ *     return 0
+ * 
+ */
+  memcpy((__pyx_v_self->data.as_chars + (__pyx_v_origsize * __pyx_v_itemsize)), __pyx_v_stuff, (__pyx_v_n * __pyx_v_itemsize));
+
+  /* "array.pxd":151
+ *     resize_smart(self, origsize + n)
+ *     memcpy(self.data.as_chars + origsize * itemsize, stuff, n * itemsize)
+ *     return 0             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline int extend(array self, array other) except -1:
+ */
+  __pyx_r = 0;
+  goto __pyx_L0;
+
+  /* "array.pxd":143
+ *     return op
+ * 
+ * cdef inline int extend_buffer(array self, char* stuff, Py_ssize_t n) except -1:             # <<<<<<<<<<<<<<
+ *     """ efficent appending of new stuff of same type
+ *     (e.g. of same array type)
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("cpython.array.extend_buffer", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "array.pxd":153
+ *     return 0
+ * 
+ * cdef inline int extend(array self, array other) except -1:             # <<<<<<<<<<<<<<
+ *     """ extend array with data from another array; types must match. """
+ *     if self.ob_descr.typecode != other.ob_descr.typecode:
+ */
+
+static CYTHON_INLINE int __pyx_f_7cpython_5array_extend(arrayobject *__pyx_v_self, arrayobject *__pyx_v_other) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  int __pyx_t_2;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("extend", 0);
+
+  /* "array.pxd":155
+ * cdef inline int extend(array self, array other) except -1:
+ *     """ extend array with data from another array; types must match. """
+ *     if self.ob_descr.typecode != other.ob_descr.typecode:             # <<<<<<<<<<<<<<
+ *         PyErr_BadArgument()
+ *     return extend_buffer(self, other.data.as_chars, Py_SIZE(other))
+ */
+  __pyx_t_1 = ((__pyx_v_self->ob_descr->typecode != __pyx_v_other->ob_descr->typecode) != 0);
+  if (__pyx_t_1) {
+
+    /* "array.pxd":156
+ *     """ extend array with data from another array; types must match. """
+ *     if self.ob_descr.typecode != other.ob_descr.typecode:
+ *         PyErr_BadArgument()             # <<<<<<<<<<<<<<
+ *     return extend_buffer(self, other.data.as_chars, Py_SIZE(other))
+ * 
+ */
+    __pyx_t_2 = PyErr_BadArgument(); if (unlikely(__pyx_t_2 == 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L3;
+  }
+  __pyx_L3:;
+
+  /* "array.pxd":157
+ *     if self.ob_descr.typecode != other.ob_descr.typecode:
+ *         PyErr_BadArgument()
+ *     return extend_buffer(self, other.data.as_chars, Py_SIZE(other))             # <<<<<<<<<<<<<<
+ * 
+ * cdef inline void zero(array self):
+ */
+  __pyx_t_2 = __pyx_f_7cpython_5array_extend_buffer(__pyx_v_self, __pyx_v_other->data.as_chars, Py_SIZE(((PyObject *)__pyx_v_other))); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_t_2;
+  goto __pyx_L0;
+
+  /* "array.pxd":153
+ *     return 0
+ * 
+ * cdef inline int extend(array self, array other) except -1:             # <<<<<<<<<<<<<<
+ *     """ extend array with data from another array; types must match. """
+ *     if self.ob_descr.typecode != other.ob_descr.typecode:
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("cpython.array.extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "array.pxd":159
+ *     return extend_buffer(self, other.data.as_chars, Py_SIZE(other))
+ * 
+ * cdef inline void zero(array self):             # <<<<<<<<<<<<<<
+ *     """ set all elements of array to zero. """
+ *     memset(self.data.as_chars, 0, Py_SIZE(self) * self.ob_descr.itemsize)
+ */
+
+static CYTHON_INLINE void __pyx_f_7cpython_5array_zero(arrayobject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("zero", 0);
+
+  /* "array.pxd":161
+ * cdef inline void zero(array self):
+ *     """ set all elements of array to zero. """
+ *     memset(self.data.as_chars, 0, Py_SIZE(self) * self.ob_descr.itemsize)             # <<<<<<<<<<<<<<
+ */
+  memset(__pyx_v_self->data.as_chars, 0, (Py_SIZE(((PyObject *)__pyx_v_self)) * __pyx_v_self->ob_descr->itemsize));
+
+  /* "array.pxd":159
+ *     return extend_buffer(self, other.data.as_chars, Py_SIZE(other))
+ * 
+ * cdef inline void zero(array self):             # <<<<<<<<<<<<<<
+ *     """ set all elements of array to zero. """
+ *     memset(self.data.as_chars, 0, Py_SIZE(self) * self.ob_descr.itemsize)
+ */
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "string.from_py":13
+ * 
+ * @cname("__pyx_convert_string_from_py_std__string")
+ * cdef string __pyx_convert_string_from_py_std__string(object o) except *:             # <<<<<<<<<<<<<<
+ *     cdef Py_ssize_t length
+ *     cdef char* data = __Pyx_PyObject_AsStringAndSize(o, &length)
+ */
+
+static std::string __pyx_convert_string_from_py_std__string(PyObject *__pyx_v_o) {
+  Py_ssize_t __pyx_v_length;
+  char *__pyx_v_data;
+  std::string __pyx_r;
+  __Pyx_RefNannyDeclarations
+  char *__pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__pyx_convert_string_from_py_std__string", 0);
+
+  /* "string.from_py":15
+ * cdef string __pyx_convert_string_from_py_std__string(object o) except *:
+ *     cdef Py_ssize_t length
+ *     cdef char* data = __Pyx_PyObject_AsStringAndSize(o, &length)             # <<<<<<<<<<<<<<
+ *     return string(data, length)
+ * 
+ */
+  __pyx_t_1 = __Pyx_PyObject_AsStringAndSize(__pyx_v_o, (&__pyx_v_length)); if (unlikely(__pyx_t_1 == NULL)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_data = __pyx_t_1;
+
+  /* "string.from_py":16
+ *     cdef Py_ssize_t length
+ *     cdef char* data = __Pyx_PyObject_AsStringAndSize(o, &length)
+ *     return string(data, length)             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __pyx_r = std::string(__pyx_v_data, __pyx_v_length);
+  goto __pyx_L0;
+
+  /* "string.from_py":13
+ * 
+ * @cname("__pyx_convert_string_from_py_std__string")
+ * cdef string __pyx_convert_string_from_py_std__string(object o) except *:             # <<<<<<<<<<<<<<
+ *     cdef Py_ssize_t length
+ *     cdef char* data = __Pyx_PyObject_AsStringAndSize(o, &length)
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("string.from_py.__pyx_convert_string_from_py_std__string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "string.to_py":33
+ * 
+ * @cname("__pyx_convert_PyObject_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyObject_string_to_py_std__string(const string& s):             # <<<<<<<<<<<<<<
+ *     return __Pyx_PyObject_FromStringAndSize(s.data(), s.size())
+ * 
+ */
+
+static CYTHON_INLINE PyObject *__pyx_convert_PyObject_string_to_py_std__string(std::string const &__pyx_v_s) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__pyx_convert_PyObject_string_to_py_std__string", 0);
+
+  /* "string.to_py":34
+ * @cname("__pyx_convert_PyObject_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyObject_string_to_py_std__string(const string& s):
+ *     return __Pyx_PyObject_FromStringAndSize(s.data(), s.size())             # <<<<<<<<<<<<<<
+ * 
+ * @cname("__pyx_convert_PyUnicode_string_to_py_std__string")
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyObject_FromStringAndSize(__pyx_v_s.data(), __pyx_v_s.size()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "string.to_py":33
+ * 
+ * @cname("__pyx_convert_PyObject_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyObject_string_to_py_std__string(const string& s):             # <<<<<<<<<<<<<<
+ *     return __Pyx_PyObject_FromStringAndSize(s.data(), s.size())
+ * 
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("string.to_py.__pyx_convert_PyObject_string_to_py_std__string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "string.to_py":37
+ * 
+ * @cname("__pyx_convert_PyUnicode_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyUnicode_string_to_py_std__string(const string& s):             # <<<<<<<<<<<<<<
+ *     return __Pyx_PyUnicode_FromStringAndSize(s.data(), s.size())
+ * 
+ */
+
+static CYTHON_INLINE PyObject *__pyx_convert_PyUnicode_string_to_py_std__string(std::string const &__pyx_v_s) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__pyx_convert_PyUnicode_string_to_py_std__string", 0);
+
+  /* "string.to_py":38
+ * @cname("__pyx_convert_PyUnicode_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyUnicode_string_to_py_std__string(const string& s):
+ *     return __Pyx_PyUnicode_FromStringAndSize(s.data(), s.size())             # <<<<<<<<<<<<<<
+ * 
+ * @cname("__pyx_convert_PyBytes_string_to_py_std__string")
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyUnicode_FromStringAndSize(__pyx_v_s.data(), __pyx_v_s.size()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "string.to_py":37
+ * 
+ * @cname("__pyx_convert_PyUnicode_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyUnicode_string_to_py_std__string(const string& s):             # <<<<<<<<<<<<<<
+ *     return __Pyx_PyUnicode_FromStringAndSize(s.data(), s.size())
+ * 
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("string.to_py.__pyx_convert_PyUnicode_string_to_py_std__string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "string.to_py":41
+ * 
+ * @cname("__pyx_convert_PyBytes_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyBytes_string_to_py_std__string(const string& s):             # <<<<<<<<<<<<<<
+ *     return __Pyx_PyBytes_FromStringAndSize(s.data(), s.size())
+ * 
+ */
+
+static CYTHON_INLINE PyObject *__pyx_convert_PyBytes_string_to_py_std__string(std::string const &__pyx_v_s) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__pyx_convert_PyBytes_string_to_py_std__string", 0);
+
+  /* "string.to_py":42
+ * @cname("__pyx_convert_PyBytes_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyBytes_string_to_py_std__string(const string& s):
+ *     return __Pyx_PyBytes_FromStringAndSize(s.data(), s.size())             # <<<<<<<<<<<<<<
+ * 
+ * @cname("__pyx_convert_PyByteArray_string_to_py_std__string")
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyBytes_FromStringAndSize(__pyx_v_s.data(), __pyx_v_s.size()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "string.to_py":41
+ * 
+ * @cname("__pyx_convert_PyBytes_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyBytes_string_to_py_std__string(const string& s):             # <<<<<<<<<<<<<<
+ *     return __Pyx_PyBytes_FromStringAndSize(s.data(), s.size())
+ * 
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("string.to_py.__pyx_convert_PyBytes_string_to_py_std__string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "string.to_py":45
+ * 
+ * @cname("__pyx_convert_PyByteArray_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyByteArray_string_to_py_std__string(const string& s):             # <<<<<<<<<<<<<<
+ *     return __Pyx_PyByteArray_FromStringAndSize(s.data(), s.size())
+ * 
+ */
+
+static CYTHON_INLINE PyObject *__pyx_convert_PyByteArray_string_to_py_std__string(std::string const &__pyx_v_s) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__pyx_convert_PyByteArray_string_to_py_std__string", 0);
+
+  /* "string.to_py":46
+ * @cname("__pyx_convert_PyByteArray_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyByteArray_string_to_py_std__string(const string& s):
+ *     return __Pyx_PyByteArray_FromStringAndSize(s.data(), s.size())             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyByteArray_FromStringAndSize(__pyx_v_s.data(), __pyx_v_s.size()); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "string.to_py":45
+ * 
+ * @cname("__pyx_convert_PyByteArray_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyByteArray_string_to_py_std__string(const string& s):             # <<<<<<<<<<<<<<
+ *     return __Pyx_PyByteArray_FromStringAndSize(s.data(), s.size())
+ * 
+ */
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("string.to_py.__pyx_convert_PyByteArray_string_to_py_std__string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+static struct __pyx_vtabstruct_7pymusic_Setup __pyx_vtable_7pymusic_Setup;
+
+static PyObject *__pyx_tp_new_7pymusic_Setup(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_Setup *p;
+  PyObject *o;
+  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
+    o = (*t->tp_alloc)(t, 0);
+  } else {
+    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
+  }
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_Setup *)o);
+  p->__pyx_vtab = __pyx_vtabptr_7pymusic_Setup;
+  p->argv = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  p->comm = ((struct PyMPIIntracommObject *)Py_None); Py_INCREF(Py_None);
+  p->ports = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  if (unlikely(__pyx_pw_7pymusic_5Setup_1__cinit__(o, a, k) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic_Setup(PyObject *o) {
+  struct __pyx_obj_7pymusic_Setup *p = (struct __pyx_obj_7pymusic_Setup *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  {
+    PyObject *etype, *eval, *etb;
+    PyErr_Fetch(&etype, &eval, &etb);
+    ++Py_REFCNT(o);
+    __pyx_pw_7pymusic_5Setup_3__dealloc__(o);
+    --Py_REFCNT(o);
+    PyErr_Restore(etype, eval, etb);
+  }
+  Py_CLEAR(p->argv);
+  Py_CLEAR(p->comm);
+  Py_CLEAR(p->ports);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_7pymusic_Setup(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic_Setup *p = (struct __pyx_obj_7pymusic_Setup *)o;
+  if (p->argv) {
+    e = (*v)(p->argv, a); if (e) return e;
+  }
+  if (p->comm) {
+    e = (*v)(((PyObject*)p->comm), a); if (e) return e;
+  }
+  if (p->ports) {
+    e = (*v)(p->ports, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic_Setup(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic_Setup *p = (struct __pyx_obj_7pymusic_Setup *)o;
+  tmp = ((PyObject*)p->argv);
+  p->argv = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->comm);
+  p->comm = ((struct PyMPIIntracommObject *)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->ports);
+  p->ports = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyObject *__pyx_getprop_7pymusic_5Setup_comm(PyObject *o, CYTHON_UNUSED void *x) {
+  return __pyx_pw_7pymusic_5Setup_4comm_1__get__(o);
+}
+
+static PyMethodDef __pyx_methods_7pymusic_Setup[] = {
+  {"getcomm", (PyCFunction)__pyx_pw_7pymusic_5Setup_5getcomm, METH_NOARGS, __pyx_doc_7pymusic_5Setup_4getcomm},
+  {"config", (PyCFunction)__pyx_pw_7pymusic_5Setup_7config, METH_O, __pyx_doc_7pymusic_5Setup_6config},
+  {"publishContInput", (PyCFunction)__pyx_pw_7pymusic_5Setup_9publishContInput, METH_O, __pyx_doc_7pymusic_5Setup_8publishContInput},
+  {"publishContOutput", (PyCFunction)__pyx_pw_7pymusic_5Setup_11publishContOutput, METH_O, __pyx_doc_7pymusic_5Setup_10publishContOutput},
+  {"publishEventOutput", (PyCFunction)__pyx_pw_7pymusic_5Setup_13publishEventOutput, METH_O, __pyx_doc_7pymusic_5Setup_12publishEventOutput},
+  {"publishEventInput", (PyCFunction)__pyx_pw_7pymusic_5Setup_15publishEventInput, METH_O, __pyx_doc_7pymusic_5Setup_14publishEventInput},
+  {"publishMessageOutput", (PyCFunction)__pyx_pw_7pymusic_5Setup_17publishMessageOutput, METH_O, __pyx_doc_7pymusic_5Setup_16publishMessageOutput},
+  {"publishMessageInput", (PyCFunction)__pyx_pw_7pymusic_5Setup_19publishMessageInput, METH_O, __pyx_doc_7pymusic_5Setup_18publishMessageInput},
+  {"runtime", (PyCFunction)__pyx_pw_7pymusic_5Setup_21runtime, METH_O, __pyx_doc_7pymusic_5Setup_20runtime},
+  {0, 0, 0, 0}
+};
+
+static struct PyGetSetDef __pyx_getsets_7pymusic_Setup[] = {
+  {(char *)"comm", __pyx_getprop_7pymusic_5Setup_comm, 0, 0, 0},
+  {0, 0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_Setup = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.Setup", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_Setup), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_Setup, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  "\n    API to setup the music interface.\n    Becomes invalid after a Runtime object is created.\n    It gives access to config variables (*.music file),\n    and creates sinks and sources which can then be configured with\n    the respective map method of each.\n    ", /*tp_doc*/
+  __pyx_tp_traverse_7pymusic_Setup, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic_Setup, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_Setup, /*tp_methods*/
+  0, /*tp_members*/
+  __pyx_getsets_7pymusic_Setup, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_Setup, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+
+static PyObject *__pyx_tp_new_7pymusic_Runtime(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_Runtime *p;
+  PyObject *o;
+  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
+    o = (*t->tp_alloc)(t, 0);
+  } else {
+    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
+  }
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_Runtime *)o);
+  p->comm = ((struct PyMPIIntracommObject *)Py_None); Py_INCREF(Py_None);
+  p->ports = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  if (unlikely(__pyx_pw_7pymusic_7Runtime_1__cinit__(o, a, k) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic_Runtime(PyObject *o) {
+  struct __pyx_obj_7pymusic_Runtime *p = (struct __pyx_obj_7pymusic_Runtime *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  {
+    PyObject *etype, *eval, *etb;
+    PyErr_Fetch(&etype, &eval, &etb);
+    ++Py_REFCNT(o);
+    __pyx_pw_7pymusic_7Runtime_3__dealloc__(o);
+    --Py_REFCNT(o);
+    PyErr_Restore(etype, eval, etb);
+  }
+  Py_CLEAR(p->comm);
+  Py_CLEAR(p->ports);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_7pymusic_Runtime(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic_Runtime *p = (struct __pyx_obj_7pymusic_Runtime *)o;
+  if (p->comm) {
+    e = (*v)(((PyObject*)p->comm), a); if (e) return e;
+  }
+  if (p->ports) {
+    e = (*v)(p->ports, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic_Runtime(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic_Runtime *p = (struct __pyx_obj_7pymusic_Runtime *)o;
+  tmp = ((PyObject*)p->comm);
+  p->comm = ((struct PyMPIIntracommObject *)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->ports);
+  p->ports = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyObject *__pyx_getprop_7pymusic_7Runtime_comm(PyObject *o, CYTHON_UNUSED void *x) {
+  return __pyx_pw_7pymusic_7Runtime_4comm_1__get__(o);
+}
+
+static PyMethodDef __pyx_methods_7pymusic_Runtime[] = {
+  {"time", (PyCFunction)__pyx_pw_7pymusic_7Runtime_5time, METH_NOARGS, 0},
+  {"tick", (PyCFunction)__pyx_pw_7pymusic_7Runtime_7tick, METH_NOARGS, 0},
+  {0, 0, 0, 0}
+};
+
+static struct PyGetSetDef __pyx_getsets_7pymusic_Runtime[] = {
+  {(char *)"comm", __pyx_getprop_7pymusic_7Runtime_comm, 0, 0, 0},
+  {0, 0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_Runtime = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.Runtime", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_Runtime), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_Runtime, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  0, /*tp_doc*/
+  __pyx_tp_traverse_7pymusic_Runtime, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic_Runtime, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  __pyx_pw_7pymusic_7Runtime_9__iter__, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_Runtime, /*tp_methods*/
+  0, /*tp_members*/
+  __pyx_getsets_7pymusic_Runtime, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_Runtime, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+static struct __pyx_vtabstruct_7pymusic_Port __pyx_vtable_7pymusic_Port;
+
+static PyObject *__pyx_tp_new_7pymusic_Port(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
+  struct __pyx_obj_7pymusic_Port *p;
+  PyObject *o;
+  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
+    o = (*t->tp_alloc)(t, 0);
+  } else {
+    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
+  }
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_Port *)o);
+  p->__pyx_vtab = __pyx_vtabptr_7pymusic_Port;
+  if (unlikely(__pyx_pw_7pymusic_4Port_1__cinit__(o, __pyx_empty_tuple, NULL) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic_Port(PyObject *o) {
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && (!PyType_IS_GC(Py_TYPE(o)) || !_PyGC_FINALIZED(o))) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static PyMethodDef __pyx_methods_7pymusic_Port[] = {
+  {"null", (PyCFunction)__pyx_pw_7pymusic_4Port_5null, METH_NOARGS, __pyx_doc_7pymusic_4Port_4null},
+  {"isConnected", (PyCFunction)__pyx_pw_7pymusic_4Port_7isConnected, METH_NOARGS, __pyx_doc_7pymusic_4Port_6isConnected},
+  {"width", (PyCFunction)__pyx_pw_7pymusic_4Port_9width, METH_NOARGS, __pyx_doc_7pymusic_4Port_8width},
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_Port = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.Port", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_Port), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_Port, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  __pyx_pw_7pymusic_4Port_3__hash__, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  "\n    Base Port class.\n\n    The underlying pointer is not deallocated here, since in MUSIC the\n    port is owned by Setup/Runtime.  This does null the value when we\n    believe the underlying object may be deallocated by the\n    container.\n    ", /*tp_doc*/
+  0, /*tp_traverse*/
+  0, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_Port, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_Port, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+static struct __pyx_vtabstruct_7pymusic_ContInputPort __pyx_vtable_7pymusic_ContInputPort;
+
+static PyObject *__pyx_tp_new_7pymusic_ContInputPort(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_ContInputPort *p;
+  PyObject *o = __pyx_tp_new_7pymusic_Port(t, a, k);
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_ContInputPort *)o);
+  p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_7pymusic_Port*)__pyx_vtabptr_7pymusic_ContInputPort;
+  return o;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_ContInputPort[] = {
+  {"map", (PyCFunction)__pyx_pw_7pymusic_13ContInputPort_1map, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7pymusic_13ContInputPort_map},
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_ContInputPort = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.ContInputPort", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_ContInputPort), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_Port, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  "\n    ContInputPort maps data indices between sources and sinks. This is\n    the sink side; source is ContOutputPort. Created by\n    Setup.publishContInputPort(portname).\n    ", /*tp_doc*/
+  0, /*tp_traverse*/
+  0, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_ContInputPort, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_ContInputPort, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+static struct __pyx_vtabstruct_7pymusic_ContOutputPort __pyx_vtable_7pymusic_ContOutputPort;
+
+static PyObject *__pyx_tp_new_7pymusic_ContOutputPort(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_ContOutputPort *p;
+  PyObject *o = __pyx_tp_new_7pymusic_Port(t, a, k);
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_ContOutputPort *)o);
+  p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_7pymusic_Port*)__pyx_vtabptr_7pymusic_ContOutputPort;
+  return o;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_ContOutputPort[] = {
+  {"map", (PyCFunction)__pyx_pw_7pymusic_14ContOutputPort_1map, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7pymusic_14ContOutputPort_map},
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_ContOutputPort = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.ContOutputPort", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_ContOutputPort), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_Port, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  "\n    ContOutputPort maps data indices between sources and sinks. This\n    is the source side; ContInputPort is the sink. Created by\n    Setup.publishContOutputPort(portname).\n    ", /*tp_doc*/
+  0, /*tp_traverse*/
+  0, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_ContOutputPort, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_ContOutputPort, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+static struct __pyx_vtabstruct_7pymusic_EventInputPort __pyx_vtable_7pymusic_EventInputPort;
+
+static PyObject *__pyx_tp_new_7pymusic_EventInputPort(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_EventInputPort *p;
+  PyObject *o = __pyx_tp_new_7pymusic_Port(t, a, k);
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_EventInputPort *)o);
+  p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_7pymusic_Port*)__pyx_vtabptr_7pymusic_EventInputPort;
+  p->events = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  if (unlikely(__pyx_pw_7pymusic_14EventInputPort_1__cinit__(o, __pyx_empty_tuple, NULL) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic_EventInputPort(PyObject *o) {
+  struct __pyx_obj_7pymusic_EventInputPort *p = (struct __pyx_obj_7pymusic_EventInputPort *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  Py_CLEAR(p->events);
+  #if CYTHON_COMPILING_IN_CPYTHON
+  if (PyType_IS_GC(Py_TYPE(o)->tp_base))
+  #endif
+  PyObject_GC_Track(o);
+  __pyx_tp_dealloc_7pymusic_Port(o);
+}
+
+static int __pyx_tp_traverse_7pymusic_EventInputPort(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic_EventInputPort *p = (struct __pyx_obj_7pymusic_EventInputPort *)o;
+  e = ((likely(__pyx_ptype_7pymusic_Port)) ? ((__pyx_ptype_7pymusic_Port->tp_traverse) ? __pyx_ptype_7pymusic_Port->tp_traverse(o, v, a) : 0) : __Pyx_call_next_tp_traverse(o, v, a, __pyx_tp_traverse_7pymusic_EventInputPort)); if (e) return e;
+  if (p->events) {
+    e = (*v)(p->events, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic_EventInputPort(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic_EventInputPort *p = (struct __pyx_obj_7pymusic_EventInputPort *)o;
+  if (likely(__pyx_ptype_7pymusic_Port)) { if (__pyx_ptype_7pymusic_Port->tp_clear) __pyx_ptype_7pymusic_Port->tp_clear(o); } else __Pyx_call_next_tp_clear(o, __pyx_tp_clear_7pymusic_EventInputPort);
+  tmp = ((PyObject*)p->events);
+  p->events = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_EventInputPort[] = {
+  {"null", (PyCFunction)__pyx_pw_7pymusic_14EventInputPort_3null, METH_NOARGS, __pyx_doc_7pymusic_14EventInputPort_2null},
+  {"map", (PyCFunction)__pyx_pw_7pymusic_14EventInputPort_5map, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7pymusic_14EventInputPort_4map},
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_EventInputPort = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.EventInputPort", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_EventInputPort), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_EventInputPort, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  "\n    Event sink. Maps 'events' to handlers. Events are spike-like\n    events at a defined time associated with an id, either/or\n    global/local in some (unclear to me) way.\n\n    Since these 'events' must be protected from deallocation as long\n    as the port exists (until finalization), we keep a set of them\n    here and drop the reference when this object is null'd (events member).\n    ", /*tp_doc*/
+  __pyx_tp_traverse_7pymusic_EventInputPort, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic_EventInputPort, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_EventInputPort, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_EventInputPort, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+static struct __pyx_vtabstruct_7pymusic_EventOutputPort __pyx_vtable_7pymusic_EventOutputPort;
+
+static PyObject *__pyx_tp_new_7pymusic_EventOutputPort(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_EventOutputPort *p;
+  PyObject *o = __pyx_tp_new_7pymusic_Port(t, a, k);
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_EventOutputPort *)o);
+  p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_7pymusic_Port*)__pyx_vtabptr_7pymusic_EventOutputPort;
+  return o;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_EventOutputPort[] = {
+  {"map", (PyCFunction)__pyx_pw_7pymusic_15EventOutputPort_1map, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7pymusic_15EventOutputPort_map},
+  {"insertEvent", (PyCFunction)__pyx_pw_7pymusic_15EventOutputPort_3insertEvent, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7pymusic_15EventOutputPort_2insertEvent},
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_EventOutputPort = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.EventOutputPort", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_EventOutputPort), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_Port, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  "\n    Map events from this sink. See EventInputPort for description of\n    events.\n    ", /*tp_doc*/
+  0, /*tp_traverse*/
+  0, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_EventOutputPort, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_EventOutputPort, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+static struct __pyx_vtabstruct_7pymusic_MessageInputPort __pyx_vtable_7pymusic_MessageInputPort;
+
+static PyObject *__pyx_tp_new_7pymusic_MessageInputPort(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_MessageInputPort *p;
+  PyObject *o = __pyx_tp_new_7pymusic_Port(t, a, k);
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_MessageInputPort *)o);
+  p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_7pymusic_Port*)__pyx_vtabptr_7pymusic_MessageInputPort;
+  p->events = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  if (unlikely(__pyx_pw_7pymusic_16MessageInputPort_1__cinit__(o, __pyx_empty_tuple, NULL) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic_MessageInputPort(PyObject *o) {
+  struct __pyx_obj_7pymusic_MessageInputPort *p = (struct __pyx_obj_7pymusic_MessageInputPort *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  Py_CLEAR(p->events);
+  #if CYTHON_COMPILING_IN_CPYTHON
+  if (PyType_IS_GC(Py_TYPE(o)->tp_base))
+  #endif
+  PyObject_GC_Track(o);
+  __pyx_tp_dealloc_7pymusic_Port(o);
+}
+
+static int __pyx_tp_traverse_7pymusic_MessageInputPort(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic_MessageInputPort *p = (struct __pyx_obj_7pymusic_MessageInputPort *)o;
+  e = ((likely(__pyx_ptype_7pymusic_Port)) ? ((__pyx_ptype_7pymusic_Port->tp_traverse) ? __pyx_ptype_7pymusic_Port->tp_traverse(o, v, a) : 0) : __Pyx_call_next_tp_traverse(o, v, a, __pyx_tp_traverse_7pymusic_MessageInputPort)); if (e) return e;
+  if (p->events) {
+    e = (*v)(p->events, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic_MessageInputPort(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic_MessageInputPort *p = (struct __pyx_obj_7pymusic_MessageInputPort *)o;
+  if (likely(__pyx_ptype_7pymusic_Port)) { if (__pyx_ptype_7pymusic_Port->tp_clear) __pyx_ptype_7pymusic_Port->tp_clear(o); } else __Pyx_call_next_tp_clear(o, __pyx_tp_clear_7pymusic_MessageInputPort);
+  tmp = ((PyObject*)p->events);
+  p->events = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_MessageInputPort[] = {
+  {"null", (PyCFunction)__pyx_pw_7pymusic_16MessageInputPort_3null, METH_NOARGS, __pyx_doc_7pymusic_16MessageInputPort_2null},
+  {"map", (PyCFunction)__pyx_pw_7pymusic_16MessageInputPort_5map, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7pymusic_16MessageInputPort_4map},
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_MessageInputPort = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.MessageInputPort", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_MessageInputPort), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_MessageInputPort, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  "\n    Maps 'events' to handlers.\n\n    Since these 'events' must be protected from deallocation as long\n    as the port exists (until finalization), we keep a set of them\n    here and drop the reference when this object is null'd.\n    ", /*tp_doc*/
+  __pyx_tp_traverse_7pymusic_MessageInputPort, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic_MessageInputPort, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_MessageInputPort, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_MessageInputPort, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+static struct __pyx_vtabstruct_7pymusic_MessageOutputPort __pyx_vtable_7pymusic_MessageOutputPort;
+
+static PyObject *__pyx_tp_new_7pymusic_MessageOutputPort(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_MessageOutputPort *p;
+  PyObject *o = __pyx_tp_new_7pymusic_Port(t, a, k);
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_MessageOutputPort *)o);
+  p->__pyx_base.__pyx_vtab = (struct __pyx_vtabstruct_7pymusic_Port*)__pyx_vtabptr_7pymusic_MessageOutputPort;
+  return o;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_MessageOutputPort[] = {
+  {"map", (PyCFunction)__pyx_pw_7pymusic_17MessageOutputPort_1map, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7pymusic_17MessageOutputPort_map},
+  {"insertMessage", (PyCFunction)__pyx_pw_7pymusic_17MessageOutputPort_3insertMessage, METH_VARARGS|METH_KEYWORDS, __pyx_doc_7pymusic_17MessageOutputPort_2insertMessage},
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_MessageOutputPort = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.MessageOutputPort", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_MessageOutputPort), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_Port, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  "\n    The source of \"messages\". A message is a python object that is\n    pickled and fed to the other end, associated with a time.\n    ", /*tp_doc*/
+  0, /*tp_traverse*/
+  0, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_MessageOutputPort, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_MessageOutputPort, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+
+static PyObject *__pyx_tp_new_7pymusic_DataMap(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_DataMap *p;
+  PyObject *o;
+  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
+    o = (*t->tp_alloc)(t, 0);
+  } else {
+    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
+  }
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_DataMap *)o);
+  p->buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)Py_None); Py_INCREF(Py_None);
+  if (unlikely(__pyx_pw_7pymusic_7DataMap_1__cinit__(o, a, k) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic_DataMap(PyObject *o) {
+  struct __pyx_obj_7pymusic_DataMap *p = (struct __pyx_obj_7pymusic_DataMap *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  {
+    PyObject *etype, *eval, *etb;
+    PyErr_Fetch(&etype, &eval, &etb);
+    ++Py_REFCNT(o);
+    __pyx_pw_7pymusic_7DataMap_3__dealloc__(o);
+    --Py_REFCNT(o);
+    PyErr_Restore(etype, eval, etb);
+  }
+  Py_CLEAR(p->buf);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_7pymusic_DataMap(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic_DataMap *p = (struct __pyx_obj_7pymusic_DataMap *)o;
+  if (p->buf) {
+    e = (*v)(((PyObject*)p->buf), a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic_DataMap(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic_DataMap *p = (struct __pyx_obj_7pymusic_DataMap *)o;
+  tmp = ((PyObject*)p->buf);
+  p->buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_DataMap[] = {
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_DataMap = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.DataMap", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_DataMap), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_DataMap, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  "\n    Internal:\n    An ArrayData object. Takes a data object as a Buffer and possibly an\n    IndexMap to construct a mapping for the Cont*Port transfers.\n    ", /*tp_doc*/
+  __pyx_tp_traverse_7pymusic_DataMap, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic_DataMap, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_DataMap, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_DataMap, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+
+static PyObject *__pyx_tp_new_7pymusic_IndexMap(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_IndexMap *p;
+  PyObject *o;
+  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
+    o = (*t->tp_alloc)(t, 0);
+  } else {
+    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
+  }
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_IndexMap *)o);
+  p->buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)Py_None); Py_INCREF(Py_None);
+  if (unlikely(__pyx_pw_7pymusic_8IndexMap_1__cinit__(o, a, k) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic_IndexMap(PyObject *o) {
+  struct __pyx_obj_7pymusic_IndexMap *p = (struct __pyx_obj_7pymusic_IndexMap *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  {
+    PyObject *etype, *eval, *etb;
+    PyErr_Fetch(&etype, &eval, &etb);
+    ++Py_REFCNT(o);
+    __pyx_pw_7pymusic_8IndexMap_3__dealloc__(o);
+    --Py_REFCNT(o);
+    PyErr_Restore(etype, eval, etb);
+  }
+  Py_CLEAR(p->buf);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_7pymusic_IndexMap(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic_IndexMap *p = (struct __pyx_obj_7pymusic_IndexMap *)o;
+  if (p->buf) {
+    e = (*v)(((PyObject*)p->buf), a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic_IndexMap(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic_IndexMap *p = (struct __pyx_obj_7pymusic_IndexMap *)o;
+  tmp = ((PyObject*)p->buf);
+  p->buf = ((struct __pyx_obj_5music_8pybuffer_Buffer *)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_IndexMap[] = {
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_IndexMap = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.IndexMap", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_IndexMap), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_IndexMap, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  "\n    Internal:\n    Contains a C++ LinearIndex or PermutationIndex.\n    These map between \"local\" index i to \"global\" index j\n    LinearIndex: g = l + base, for l < size\n    PermutationIndex: g = perm[l], where perm is an array\n    ", /*tp_doc*/
+  __pyx_tp_traverse_7pymusic_IndexMap, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic_IndexMap, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_IndexMap, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_IndexMap, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+
+static PyObject *__pyx_tp_new_7pymusic_EventHandler(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_EventHandler *p;
+  PyObject *o;
+  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
+    o = (*t->tp_alloc)(t, 0);
+  } else {
+    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
+  }
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_EventHandler *)o);
+  p->func = Py_None; Py_INCREF(Py_None);
+  if (unlikely(__pyx_pw_7pymusic_12EventHandler_1__cinit__(o, a, k) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic_EventHandler(PyObject *o) {
+  struct __pyx_obj_7pymusic_EventHandler *p = (struct __pyx_obj_7pymusic_EventHandler *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  {
+    PyObject *etype, *eval, *etb;
+    PyErr_Fetch(&etype, &eval, &etb);
+    ++Py_REFCNT(o);
+    __pyx_pw_7pymusic_12EventHandler_3__dealloc__(o);
+    --Py_REFCNT(o);
+    PyErr_Restore(etype, eval, etb);
+  }
+  Py_CLEAR(p->func);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_7pymusic_EventHandler(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic_EventHandler *p = (struct __pyx_obj_7pymusic_EventHandler *)o;
+  if (p->func) {
+    e = (*v)(p->func, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic_EventHandler(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic_EventHandler *p = (struct __pyx_obj_7pymusic_EventHandler *)o;
+  tmp = ((PyObject*)p->func);
+  p->func = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_EventHandler[] = {
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_EventHandler = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.EventHandler", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_EventHandler), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_EventHandler, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  "\n    Internal:\n    An EventHandler is the python wrapper around a global\n    or local EventHandler object for EventInputPort\n    ", /*tp_doc*/
+  __pyx_tp_traverse_7pymusic_EventHandler, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic_EventHandler, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_EventHandler, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_EventHandler, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+
+static PyObject *__pyx_tp_new_7pymusic_MessageHandler(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_7pymusic_MessageHandler *p;
+  PyObject *o;
+  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
+    o = (*t->tp_alloc)(t, 0);
+  } else {
+    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
+  }
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic_MessageHandler *)o);
+  p->func = Py_None; Py_INCREF(Py_None);
+  if (unlikely(__pyx_pw_7pymusic_14MessageHandler_1__cinit__(o, a, k) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic_MessageHandler(PyObject *o) {
+  struct __pyx_obj_7pymusic_MessageHandler *p = (struct __pyx_obj_7pymusic_MessageHandler *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  {
+    PyObject *etype, *eval, *etb;
+    PyErr_Fetch(&etype, &eval, &etb);
+    ++Py_REFCNT(o);
+    __pyx_pw_7pymusic_14MessageHandler_3__dealloc__(o);
+    --Py_REFCNT(o);
+    PyErr_Restore(etype, eval, etb);
+  }
+  Py_CLEAR(p->func);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_7pymusic_MessageHandler(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic_MessageHandler *p = (struct __pyx_obj_7pymusic_MessageHandler *)o;
+  if (p->func) {
+    e = (*v)(p->func, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic_MessageHandler(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic_MessageHandler *p = (struct __pyx_obj_7pymusic_MessageHandler *)o;
+  tmp = ((PyObject*)p->func);
+  p->func = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyMethodDef __pyx_methods_7pymusic_MessageHandler[] = {
+  {0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic_MessageHandler = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.MessageHandler", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic_MessageHandler), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic_MessageHandler, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  "\n    MessageHandler wraps up Message*Port communications between C & python,\n    wrapping n particular the C++ MessageHandler object bound with a function.\n    It may (or may not) depickle messages\n    ", /*tp_doc*/
+  __pyx_tp_traverse_7pymusic_MessageHandler, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic_MessageHandler, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic_MessageHandler, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic_MessageHandler, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+
+static PyObject *__pyx_tp_new_7pymusic__Index(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
+  struct __pyx_obj_7pymusic__Index *p;
+  PyObject *o;
+  if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) == 0)) {
+    o = (*t->tp_alloc)(t, 0);
+  } else {
+    o = (PyObject *) PyBaseObject_Type.tp_new(t, __pyx_empty_tuple, 0);
+  }
+  if (unlikely(!o)) return 0;
+  p = ((struct __pyx_obj_7pymusic__Index *)o);
+  p->backmap = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  if (unlikely(__pyx_pw_7pymusic_6_Index_1__cinit__(o, __pyx_empty_tuple, NULL) < 0)) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic__Index(PyObject *o) {
+  struct __pyx_obj_7pymusic__Index *p = (struct __pyx_obj_7pymusic__Index *)o;
+  #if PY_VERSION_HEX >= 0x030400a1
+  if (unlikely(Py_TYPE(o)->tp_finalize) && !_PyGC_FINALIZED(o)) {
+    if (PyObject_CallFinalizerFromDealloc(o)) return;
+  }
+  #endif
+  PyObject_GC_UnTrack(o);
+  Py_CLEAR(p->backmap);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_7pymusic__Index(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic__Index *p = (struct __pyx_obj_7pymusic__Index *)o;
+  if (p->backmap) {
+    e = (*v)(p->backmap, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic__Index(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic__Index *p = (struct __pyx_obj_7pymusic__Index *)o;
+  tmp = ((PyObject*)p->backmap);
+  p->backmap = ((PyObject*)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyObject *__pyx_getprop_7pymusic_6_Index_GLOBAL(PyObject *o, CYTHON_UNUSED void *x) {
+  return __pyx_pw_7pymusic_6_Index_6GLOBAL_1__get__(o);
+}
+
+static PyObject *__pyx_getprop_7pymusic_6_Index_LOCAL(PyObject *o, CYTHON_UNUSED void *x) {
+  return __pyx_pw_7pymusic_6_Index_5LOCAL_1__get__(o);
+}
+
+static PyObject *__pyx_getprop_7pymusic_6_Index_backmap(PyObject *o, CYTHON_UNUSED void *x) {
+  return __pyx_pw_7pymusic_6_Index_7backmap_1__get__(o);
+}
+
+static PyMethodDef __pyx_methods_7pymusic__Index[] = {
+  {"tostr", (PyCFunction)__pyx_pw_7pymusic_6_Index_3tostr, METH_O, __pyx_doc_7pymusic_6_Index_2tostr},
+  {0, 0, 0, 0}
+};
+
+static struct PyGetSetDef __pyx_getsets_7pymusic__Index[] = {
+  {(char *)"GLOBAL", __pyx_getprop_7pymusic_6_Index_GLOBAL, 0, 0, 0},
+  {(char *)"LOCAL", __pyx_getprop_7pymusic_6_Index_LOCAL, 0, 0, 0},
+  {(char *)"backmap", __pyx_getprop_7pymusic_6_Index_backmap, 0, 0, 0},
+  {0, 0, 0, 0, 0}
+};
+
+static PyTypeObject __pyx_type_7pymusic__Index = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic._Index", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic__Index), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic__Index, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  "\n    Internal: the type of the variable Index\n    that encapsulates the enum mapping\n    GLOBAL and LOCAL are the ints of the C enums\n    backmap maps from the enum to a string for output\n    purposes\n    ", /*tp_doc*/
+  __pyx_tp_traverse_7pymusic__Index, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic__Index, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_7pymusic__Index, /*tp_methods*/
+  0, /*tp_members*/
+  __pyx_getsets_7pymusic__Index, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic__Index, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+
+static struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *__pyx_freelist_7pymusic___pyx_scope_struct____iter__[8];
+static int __pyx_freecount_7pymusic___pyx_scope_struct____iter__ = 0;
+
+static PyObject *__pyx_tp_new_7pymusic___pyx_scope_struct____iter__(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
+  PyObject *o;
+  if (CYTHON_COMPILING_IN_CPYTHON && likely((__pyx_freecount_7pymusic___pyx_scope_struct____iter__ > 0) & (t->tp_basicsize == sizeof(struct __pyx_obj_7pymusic___pyx_scope_struct____iter__)))) {
+    o = (PyObject*)__pyx_freelist_7pymusic___pyx_scope_struct____iter__[--__pyx_freecount_7pymusic___pyx_scope_struct____iter__];
+    memset(o, 0, sizeof(struct __pyx_obj_7pymusic___pyx_scope_struct____iter__));
+    (void) PyObject_INIT(o, t);
+    PyObject_GC_Track(o);
+  } else {
+    o = (*t->tp_alloc)(t, 0);
+    if (unlikely(!o)) return 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_7pymusic___pyx_scope_struct____iter__(PyObject *o) {
+  struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *p = (struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *)o;
+  PyObject_GC_UnTrack(o);
+  Py_CLEAR(p->__pyx_v_self);
+  if (CYTHON_COMPILING_IN_CPYTHON && ((__pyx_freecount_7pymusic___pyx_scope_struct____iter__ < 8) & (Py_TYPE(o)->tp_basicsize == sizeof(struct __pyx_obj_7pymusic___pyx_scope_struct____iter__)))) {
+    __pyx_freelist_7pymusic___pyx_scope_struct____iter__[__pyx_freecount_7pymusic___pyx_scope_struct____iter__++] = ((struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *)o);
+  } else {
+    (*Py_TYPE(o)->tp_free)(o);
+  }
+}
+
+static int __pyx_tp_traverse_7pymusic___pyx_scope_struct____iter__(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *p = (struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *)o;
+  if (p->__pyx_v_self) {
+    e = (*v)(((PyObject*)p->__pyx_v_self), a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_7pymusic___pyx_scope_struct____iter__(PyObject *o) {
+  PyObject* tmp;
+  struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *p = (struct __pyx_obj_7pymusic___pyx_scope_struct____iter__ *)o;
+  tmp = ((PyObject*)p->__pyx_v_self);
+  p->__pyx_v_self = ((struct __pyx_obj_7pymusic_Runtime *)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyTypeObject __pyx_type_7pymusic___pyx_scope_struct____iter__ = {
+  PyVarObject_HEAD_INIT(0, 0)
+  "pymusic.__pyx_scope_struct____iter__", /*tp_name*/
+  sizeof(struct __pyx_obj_7pymusic___pyx_scope_struct____iter__), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_7pymusic___pyx_scope_struct____iter__, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  0, /*tp_as_number*/
+  0, /*tp_as_sequence*/
+  0, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  0, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  0, /*tp_doc*/
+  __pyx_tp_traverse_7pymusic___pyx_scope_struct____iter__, /*tp_traverse*/
+  __pyx_tp_clear_7pymusic___pyx_scope_struct____iter__, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  0, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_7pymusic___pyx_scope_struct____iter__, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  0, /*tp_version_tag*/
+  #if PY_VERSION_HEX >= 0x030400a1
+  0, /*tp_finalize*/
+  #endif
+};
+
+static PyMethodDef __pyx_methods[] = {
+  {0, 0, 0, 0}
+};
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef __pyx_moduledef = {
+  #if PY_VERSION_HEX < 0x03020000
+    { PyObject_HEAD_INIT(NULL) NULL, 0, NULL },
+  #else
+    PyModuleDef_HEAD_INIT,
+  #endif
+    "pymusic",
+    0, /* m_doc */
+    -1, /* m_size */
+    __pyx_methods /* m_methods */,
+    NULL, /* m_reload */
+    NULL, /* m_traverse */
+    NULL, /* m_clear */
+    NULL /* m_free */
+};
+#endif
+
+static __Pyx_StringTabEntry __pyx_string_tab[] = {
+  {&__pyx_kp_s_All_exceptions_in_pymusic_are_M, __pyx_k_All_exceptions_in_pymusic_are_M, sizeof(__pyx_k_All_exceptions_in_pymusic_are_M), 0, 0, 1, 0},
+  {&__pyx_n_s_Buffer, __pyx_k_Buffer, sizeof(__pyx_k_Buffer), 0, 0, 1, 1},
+  {&__pyx_n_s_COMM_NULL, __pyx_k_COMM_NULL, sizeof(__pyx_k_COMM_NULL), 0, 0, 1, 1},
+  {&__pyx_kp_s_Config_variable_is_not_defined, __pyx_k_Config_variable_is_not_defined, sizeof(__pyx_k_Config_variable_is_not_defined), 0, 0, 1, 0},
+  {&__pyx_n_s_Exception, __pyx_k_Exception, sizeof(__pyx_k_Exception), 0, 0, 1, 1},
+  {&__pyx_n_s_GLOBAL, __pyx_k_GLOBAL, sizeof(__pyx_k_GLOBAL), 0, 0, 1, 1},
+  {&__pyx_n_s_HIGHEST_PROTOCOL, __pyx_k_HIGHEST_PROTOCOL, sizeof(__pyx_k_HIGHEST_PROTOCOL), 0, 0, 1, 1},
+  {&__pyx_n_s_Index, __pyx_k_Index, sizeof(__pyx_k_Index), 0, 0, 1, 1},
+  {&__pyx_n_s_LOCAL, __pyx_k_LOCAL, sizeof(__pyx_k_LOCAL), 0, 0, 1, 1},
+  {&__pyx_n_s_MPI, __pyx_k_MPI, sizeof(__pyx_k_MPI), 0, 0, 1, 1},
+  {&__pyx_n_s_MUSICError, __pyx_k_MUSICError, sizeof(__pyx_k_MUSICError), 0, 0, 1, 1},
+  {&__pyx_n_s_MemoryError, __pyx_k_MemoryError, sizeof(__pyx_k_MemoryError), 0, 0, 1, 1},
+  {&__pyx_n_s_NoWidth, __pyx_k_NoWidth, sizeof(__pyx_k_NoWidth), 0, 0, 1, 1},
+  {&__pyx_n_s_NoWidth___init, __pyx_k_NoWidth___init, sizeof(__pyx_k_NoWidth___init), 0, 0, 1, 1},
+  {&__pyx_kp_s_No_width_defined, __pyx_k_No_width_defined, sizeof(__pyx_k_No_width_defined), 0, 0, 1, 0},
+  {&__pyx_n_s_Runtime___iter, __pyx_k_Runtime___iter, sizeof(__pyx_k_Runtime___iter), 0, 0, 1, 1},
+  {&__pyx_kp_s_Thrown_if_Port_width_is_called, __pyx_k_Thrown_if_Port_width_is_called, sizeof(__pyx_k_Thrown_if_Port_width_is_called), 0, 0, 1, 0},
+  {&__pyx_kp_s_Thrown_if_a_configuration_value, __pyx_k_Thrown_if_a_configuration_value, sizeof(__pyx_k_Thrown_if_a_configuration_value), 0, 0, 1, 0},
+  {&__pyx_n_s_UndefinedConfig, __pyx_k_UndefinedConfig, sizeof(__pyx_k_UndefinedConfig), 0, 0, 1, 1},
+  {&__pyx_n_s_UndefinedConfig___init, __pyx_k_UndefinedConfig___init, sizeof(__pyx_k_UndefinedConfig___init), 0, 0, 1, 1},
+  {&__pyx_n_s_ValueError, __pyx_k_ValueError, sizeof(__pyx_k_ValueError), 0, 0, 1, 1},
+  {&__pyx_n_s__3, __pyx_k__3, sizeof(__pyx_k__3), 0, 0, 1, 1},
+  {&__pyx_n_s_accLatency, __pyx_k_accLatency, sizeof(__pyx_k_accLatency), 0, 0, 1, 1},
+  {&__pyx_n_s_args, __pyx_k_args, sizeof(__pyx_k_args), 0, 0, 1, 1},
+  {&__pyx_n_s_argv, __pyx_k_argv, sizeof(__pyx_k_argv), 0, 0, 1, 1},
+  {&__pyx_kp_s_argv_can_t_be_empty, __pyx_k_argv_can_t_be_empty, sizeof(__pyx_k_argv_can_t_be_empty), 0, 0, 1, 0},
+  {&__pyx_n_s_array, __pyx_k_array, sizeof(__pyx_k_array), 0, 0, 1, 1},
+  {&__pyx_n_s_base, __pyx_k_base, sizeof(__pyx_k_base), 0, 0, 1, 1},
+  {&__pyx_n_s_buf, __pyx_k_buf, sizeof(__pyx_k_buf), 0, 0, 1, 1},
+  {&__pyx_n_s_cPickle, __pyx_k_cPickle, sizeof(__pyx_k_cPickle), 0, 0, 1, 1},
+  {&__pyx_n_s_close, __pyx_k_close, sizeof(__pyx_k_close), 0, 0, 1, 1},
+  {&__pyx_kp_s_couldn_t_allocate_argv, __pyx_k_couldn_t_allocate_argv, sizeof(__pyx_k_couldn_t_allocate_argv), 0, 0, 1, 0},
+  {&__pyx_n_s_data, __pyx_k_data, sizeof(__pyx_k_data), 0, 0, 1, 1},
+  {&__pyx_n_s_delay, __pyx_k_delay, sizeof(__pyx_k_delay), 0, 0, 1, 1},
+  {&__pyx_n_s_doc, __pyx_k_doc, sizeof(__pyx_k_doc), 0, 0, 1, 1},
+  {&__pyx_n_s_dumps, __pyx_k_dumps, sizeof(__pyx_k_dumps), 0, 0, 1, 1},
+  {&__pyx_n_s_encode, __pyx_k_encode, sizeof(__pyx_k_encode), 0, 0, 1, 1},
+  {&__pyx_n_s_format, __pyx_k_format, sizeof(__pyx_k_format), 0, 0, 1, 1},
+  {&__pyx_n_s_func, __pyx_k_func, sizeof(__pyx_k_func), 0, 0, 1, 1},
+  {&__pyx_n_s_getcomm, __pyx_k_getcomm, sizeof(__pyx_k_getcomm), 0, 0, 1, 1},
+  {&__pyx_n_s_h, __pyx_k_h, sizeof(__pyx_k_h), 0, 0, 1, 1},
+  {&__pyx_kp_s_home_apeyser_Code_music_pymusic, __pyx_k_home_apeyser_Code_music_pymusic, sizeof(__pyx_k_home_apeyser_Code_music_pymusic), 0, 0, 1, 0},
+  {&__pyx_n_s_i, __pyx_k_i, sizeof(__pyx_k_i), 0, 0, 1, 1},
+  {&__pyx_n_s_import, __pyx_k_import, sizeof(__pyx_k_import), 0, 0, 1, 1},
+  {&__pyx_n_s_index, __pyx_k_index, sizeof(__pyx_k_index), 0, 0, 1, 1},
+  {&__pyx_n_s_index_map, __pyx_k_index_map, sizeof(__pyx_k_index_map), 0, 0, 1, 1},
+  {&__pyx_n_s_init, __pyx_k_init, sizeof(__pyx_k_init), 0, 0, 1, 1},
+  {&__pyx_n_s_interpolate, __pyx_k_interpolate, sizeof(__pyx_k_interpolate), 0, 0, 1, 1},
+  {&__pyx_n_s_iter, __pyx_k_iter, sizeof(__pyx_k_iter), 0, 0, 1, 1},
+  {&__pyx_n_s_loads, __pyx_k_loads, sizeof(__pyx_k_loads), 0, 0, 1, 1},
+  {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1},
+  {&__pyx_n_s_maxBuffered, __pyx_k_maxBuffered, sizeof(__pyx_k_maxBuffered), 0, 0, 1, 1},
+  {&__pyx_n_s_metaclass, __pyx_k_metaclass, sizeof(__pyx_k_metaclass), 0, 0, 1, 1},
+  {&__pyx_n_s_module, __pyx_k_module, sizeof(__pyx_k_module), 0, 0, 1, 1},
+  {&__pyx_n_s_mpi4py_MPI, __pyx_k_mpi4py_MPI, sizeof(__pyx_k_mpi4py_MPI), 0, 0, 1, 1},
+  {&__pyx_n_s_msg, __pyx_k_msg, sizeof(__pyx_k_msg), 0, 0, 1, 1},
+  {&__pyx_n_s_music_pybuffer, __pyx_k_music_pybuffer, sizeof(__pyx_k_music_pybuffer), 0, 0, 1, 1},
+  {&__pyx_n_s_null, __pyx_k_null, sizeof(__pyx_k_null), 0, 0, 1, 1},
+  {&__pyx_n_s_perm, __pyx_k_perm, sizeof(__pyx_k_perm), 0, 0, 1, 1},
+  {&__pyx_n_s_pickle, __pyx_k_pickle, sizeof(__pyx_k_pickle), 0, 0, 1, 1},
+  {&__pyx_n_s_pickled, __pyx_k_pickled, sizeof(__pyx_k_pickled), 0, 0, 1, 1},
+  {&__pyx_n_s_predictRank, __pyx_k_predictRank, sizeof(__pyx_k_predictRank), 0, 0, 1, 1},
+  {&__pyx_n_s_prepare, __pyx_k_prepare, sizeof(__pyx_k_prepare), 0, 0, 1, 1},
+  {&__pyx_n_s_ptr, __pyx_k_ptr, sizeof(__pyx_k_ptr), 0, 0, 1, 1},
+  {&__pyx_n_s_pymusic, __pyx_k_pymusic, sizeof(__pyx_k_pymusic), 0, 0, 1, 1},
+  {&__pyx_n_s_pyx_vtable, __pyx_k_pyx_vtable, sizeof(__pyx_k_pyx_vtable), 0, 0, 1, 1},
+  {&__pyx_n_s_qualname, __pyx_k_qualname, sizeof(__pyx_k_qualname), 0, 0, 1, 1},
+  {&__pyx_n_s_r, __pyx_k_r, sizeof(__pyx_k_r), 0, 0, 1, 1},
+  {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1},
+  {&__pyx_n_s_required, __pyx_k_required, sizeof(__pyx_k_required), 0, 0, 1, 1},
+  {&__pyx_n_s_self, __pyx_k_self, sizeof(__pyx_k_self), 0, 0, 1, 1},
+  {&__pyx_n_s_send, __pyx_k_send, sizeof(__pyx_k_send), 0, 0, 1, 1},
+  {&__pyx_n_s_setup, __pyx_k_setup, sizeof(__pyx_k_setup), 0, 0, 1, 1},
+  {&__pyx_n_s_size, __pyx_k_size, sizeof(__pyx_k_size), 0, 0, 1, 1},
+  {&__pyx_n_s_sys, __pyx_k_sys, sizeof(__pyx_k_sys), 0, 0, 1, 1},
+  {&__pyx_n_s_t, __pyx_k_t, sizeof(__pyx_k_t), 0, 0, 1, 1},
+  {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1},
+  {&__pyx_n_s_throw, __pyx_k_throw, sizeof(__pyx_k_throw), 0, 0, 1, 1},
+  {&__pyx_n_s_time, __pyx_k_time, sizeof(__pyx_k_time), 0, 0, 1, 1},
+  {&__pyx_n_s_var, __pyx_k_var, sizeof(__pyx_k_var), 0, 0, 1, 1},
+  {&__pyx_n_s_xrange, __pyx_k_xrange, sizeof(__pyx_k_xrange), 0, 0, 1, 1},
+  {0, 0, 0, 0, 0, 0, 0}
+};
+static int __Pyx_InitCachedBuiltins(void) {
+  __pyx_builtin_Exception = __Pyx_GetBuiltinName(__pyx_n_s_Exception); if (!__pyx_builtin_Exception) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #if PY_MAJOR_VERSION >= 3
+  __pyx_builtin_xrange = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_xrange) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #else
+  __pyx_builtin_xrange = __Pyx_GetBuiltinName(__pyx_n_s_xrange); if (!__pyx_builtin_xrange) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s_ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 439; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_MemoryError = __Pyx_GetBuiltinName(__pyx_n_s_MemoryError); if (!__pyx_builtin_MemoryError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  return 0;
+  __pyx_L1_error:;
+  return -1;
+}
+
+static int __Pyx_InitCachedConstants(void) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
+
+  /* "pymusic.pyx":60
+ *     r.argc = len(argv)
+ *     if r.argc <= 0:
+ *         raise MUSICError("argv can't be empty")             # <<<<<<<<<<<<<<
+ * 
+ *     r.argv = <char**> malloc((r.argc+1) * sizeof(char*))
+ */
+  __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_s_argv_can_t_be_empty); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple_);
+  __Pyx_GIVEREF(__pyx_tuple_);
+
+  /* "pymusic.pyx":64
+ *     r.argv = <char**> malloc((r.argc+1) * sizeof(char*))
+ *     if r.argv is NULL:
+ *         raise MUSICError("couldn't allocate argv")             # <<<<<<<<<<<<<<
+ * 
+ *     cdef string
+ */
+  __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_s_couldn_t_allocate_argv); if (unlikely(!__pyx_tuple__2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__2);
+  __Pyx_GIVEREF(__pyx_tuple__2);
+
+  /* "pymusic.pyx":23
+ *     have a width defined.
+ *     """
+ *     def __init__(self):             # <<<<<<<<<<<<<<
+ *         MUSICError.__init__(self, "No width defined")
+ * 
+ */
+  __pyx_tuple__4 = PyTuple_Pack(1, __pyx_n_s_self); if (unlikely(!__pyx_tuple__4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__4);
+  __Pyx_GIVEREF(__pyx_tuple__4);
+  __pyx_codeobj__5 = (PyObject*)__Pyx_PyCode_New(1, 0, 1, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__4, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_apeyser_Code_music_pymusic, __pyx_n_s_init, 23, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":32
+ *     that has not been defined within the configuration.
+ *     """
+ *     def __init__(self, var):             # <<<<<<<<<<<<<<
+ *         MUSICError.__init__(
+ *             self,
+ */
+  __pyx_tuple__6 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_var); if (unlikely(!__pyx_tuple__6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__6);
+  __Pyx_GIVEREF(__pyx_tuple__6);
+  __pyx_codeobj__7 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__6, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_apeyser_Code_music_pymusic, __pyx_n_s_init, 32, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "pymusic.pyx":79
+ * ###########################################################
+ * 
+ * def predictRank(list argv=None):             # <<<<<<<<<<<<<<
+ *     """
+ *     Map into mpidep/predict_rank for config methods.
+ */
+  __pyx_tuple__8 = PyTuple_Pack(2, __pyx_n_s_argv, __pyx_n_s_r); if (unlikely(!__pyx_tuple__8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_tuple__8);
+  __Pyx_GIVEREF(__pyx_tuple__8);
+  __pyx_codeobj__9 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__8, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_apeyser_Code_music_pymusic, __pyx_n_s_predictRank, 79, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_RefNannyFinishContext();
+  return 0;
+  __pyx_L1_error:;
+  __Pyx_RefNannyFinishContext();
+  return -1;
+}
+
+static int __Pyx_InitGlobals(void) {
+  if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  return 0;
+  __pyx_L1_error:;
+  return -1;
+}
+
+#if PY_MAJOR_VERSION < 3
+PyMODINIT_FUNC initpymusic(void); /*proto*/
+PyMODINIT_FUNC initpymusic(void)
+#else
+PyMODINIT_FUNC PyInit_pymusic(void); /*proto*/
+PyMODINIT_FUNC PyInit_pymusic(void)
+#endif
+{
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannyDeclarations
+  #if CYTHON_REFNANNY
+  __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny");
+  if (!__Pyx_RefNanny) {
+      PyErr_Clear();
+      __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny");
+      if (!__Pyx_RefNanny)
+          Py_FatalError("failed to import 'refnanny' module");
+  }
+  #endif
+  __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_pymusic(void)", 0);
+  if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #ifdef __Pyx_CyFunction_USED
+  if (__Pyx_CyFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  #ifdef __Pyx_FusedFunction_USED
+  if (__pyx_FusedFunction_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  #ifdef __Pyx_Generator_USED
+  if (__pyx_Generator_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  /*--- Library function declarations ---*/
+  /*--- Threads initialization code ---*/
+  #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS
+  #ifdef WITH_THREAD /* Python build with threading support? */
+  PyEval_InitThreads();
+  #endif
+  #endif
+  /*--- Module creation code ---*/
+  #if PY_MAJOR_VERSION < 3
+  __pyx_m = Py_InitModule4("pymusic", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m);
+  #else
+  __pyx_m = PyModule_Create(&__pyx_moduledef);
+  #endif
+  if (unlikely(!__pyx_m)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_d);
+  __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #if CYTHON_COMPILING_IN_PYPY
+  Py_INCREF(__pyx_b);
+  #endif
+  if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  /*--- Initialize various global constants etc. ---*/
+  if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT)
+  if (__Pyx_init_sys_getdefaultencoding_params() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
+  if (__pyx_module_is_main_pymusic) {
+    if (PyObject_SetAttrString(__pyx_m, "__name__", __pyx_n_s_main) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
+  }
+  #if PY_MAJOR_VERSION >= 3
+  {
+    PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!PyDict_GetItemString(modules, "pymusic")) {
+      if (unlikely(PyDict_SetItemString(modules, "pymusic", __pyx_m) < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    }
+  }
+  #endif
+  /*--- Builtin init code ---*/
+  if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Constants init code ---*/
+  if (unlikely(__Pyx_InitCachedConstants() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Global init code ---*/
+  /*--- Variable export code ---*/
+  /*--- Function export code ---*/
+  if (__Pyx_ExportFunction("EventCallback", (void (*)(void))MUSIC::EventCallback, "bool (PyObject *, double, MUSIC::Index::Type, int)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_ExportFunction("MessageCallback", (void (*)(void))MUSIC::MessageCallback, "bool (PyObject *, double, void *, size_t, bool)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Type init code ---*/
+  __pyx_vtabptr_7pymusic_Setup = &__pyx_vtable_7pymusic_Setup;
+  __pyx_vtable_7pymusic_Setup.null = (PyObject *(*)(struct __pyx_obj_7pymusic_Setup *))__pyx_f_7pymusic_5Setup_null;
+  __pyx_vtable_7pymusic_Setup.getcomm = (struct PyMPIIntracommObject *(*)(struct __pyx_obj_7pymusic_Setup *, int __pyx_skip_dispatch))__pyx_f_7pymusic_5Setup_getcomm;
+  if (PyType_Ready(&__pyx_type_7pymusic_Setup) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_Setup.tp_print = 0;
+  if (__Pyx_SetVtable(__pyx_type_7pymusic_Setup.tp_dict, __pyx_vtabptr_7pymusic_Setup) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttrString(__pyx_m, "Setup", (PyObject *)&__pyx_type_7pymusic_Setup) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_Setup = &__pyx_type_7pymusic_Setup;
+  if (PyType_Ready(&__pyx_type_7pymusic_Runtime) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 517; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_Runtime.tp_print = 0;
+  if (PyObject_SetAttrString(__pyx_m, "Runtime", (PyObject *)&__pyx_type_7pymusic_Runtime) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 517; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_Runtime = &__pyx_type_7pymusic_Runtime;
+  __pyx_vtabptr_7pymusic_Port = &__pyx_vtable_7pymusic_Port;
+  __pyx_vtable_7pymusic_Port.null = (PyObject *(*)(struct __pyx_obj_7pymusic_Port *, int __pyx_skip_dispatch))__pyx_f_7pymusic_4Port_null;
+  if (PyType_Ready(&__pyx_type_7pymusic_Port) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_Port.tp_print = 0;
+  #if CYTHON_COMPILING_IN_CPYTHON
+  {
+    PyObject *wrapper = PyObject_GetAttrString((PyObject *)&__pyx_type_7pymusic_Port, "__hash__"); if (unlikely(!wrapper)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) {
+      __pyx_wrapperbase_7pymusic_4Port_2__hash__ = *((PyWrapperDescrObject *)wrapper)->d_base;
+      __pyx_wrapperbase_7pymusic_4Port_2__hash__.doc = __pyx_doc_7pymusic_4Port_2__hash__;
+      ((PyWrapperDescrObject *)wrapper)->d_base = &__pyx_wrapperbase_7pymusic_4Port_2__hash__;
+    }
+  }
+  #endif
+  if (__Pyx_SetVtable(__pyx_type_7pymusic_Port.tp_dict, __pyx_vtabptr_7pymusic_Port) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttrString(__pyx_m, "Port", (PyObject *)&__pyx_type_7pymusic_Port) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_Port = &__pyx_type_7pymusic_Port;
+  __pyx_vtabptr_7pymusic_ContInputPort = &__pyx_vtable_7pymusic_ContInputPort;
+  __pyx_vtable_7pymusic_ContInputPort.__pyx_base = *__pyx_vtabptr_7pymusic_Port;
+  __pyx_type_7pymusic_ContInputPort.tp_base = __pyx_ptype_7pymusic_Port;
+  if (PyType_Ready(&__pyx_type_7pymusic_ContInputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_ContInputPort.tp_print = 0;
+  if (__Pyx_SetVtable(__pyx_type_7pymusic_ContInputPort.tp_dict, __pyx_vtabptr_7pymusic_ContInputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttrString(__pyx_m, "ContInputPort", (PyObject *)&__pyx_type_7pymusic_ContInputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_ContInputPort = &__pyx_type_7pymusic_ContInputPort;
+  __pyx_vtabptr_7pymusic_ContOutputPort = &__pyx_vtable_7pymusic_ContOutputPort;
+  __pyx_vtable_7pymusic_ContOutputPort.__pyx_base = *__pyx_vtabptr_7pymusic_Port;
+  __pyx_type_7pymusic_ContOutputPort.tp_base = __pyx_ptype_7pymusic_Port;
+  if (PyType_Ready(&__pyx_type_7pymusic_ContOutputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_ContOutputPort.tp_print = 0;
+  if (__Pyx_SetVtable(__pyx_type_7pymusic_ContOutputPort.tp_dict, __pyx_vtabptr_7pymusic_ContOutputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttrString(__pyx_m, "ContOutputPort", (PyObject *)&__pyx_type_7pymusic_ContOutputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 178; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_ContOutputPort = &__pyx_type_7pymusic_ContOutputPort;
+  __pyx_vtabptr_7pymusic_EventInputPort = &__pyx_vtable_7pymusic_EventInputPort;
+  __pyx_vtable_7pymusic_EventInputPort.__pyx_base = *__pyx_vtabptr_7pymusic_Port;
+  __pyx_vtable_7pymusic_EventInputPort.__pyx_base.null = (PyObject *(*)(struct __pyx_obj_7pymusic_Port *, int __pyx_skip_dispatch))__pyx_f_7pymusic_14EventInputPort_null;
+  __pyx_type_7pymusic_EventInputPort.tp_base = __pyx_ptype_7pymusic_Port;
+  if (PyType_Ready(&__pyx_type_7pymusic_EventInputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_EventInputPort.tp_print = 0;
+  if (__Pyx_SetVtable(__pyx_type_7pymusic_EventInputPort.tp_dict, __pyx_vtabptr_7pymusic_EventInputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttrString(__pyx_m, "EventInputPort", (PyObject *)&__pyx_type_7pymusic_EventInputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_EventInputPort = &__pyx_type_7pymusic_EventInputPort;
+  __pyx_vtabptr_7pymusic_EventOutputPort = &__pyx_vtable_7pymusic_EventOutputPort;
+  __pyx_vtable_7pymusic_EventOutputPort.__pyx_base = *__pyx_vtabptr_7pymusic_Port;
+  __pyx_type_7pymusic_EventOutputPort.tp_base = __pyx_ptype_7pymusic_Port;
+  if (PyType_Ready(&__pyx_type_7pymusic_EventOutputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_EventOutputPort.tp_print = 0;
+  if (__Pyx_SetVtable(__pyx_type_7pymusic_EventOutputPort.tp_dict, __pyx_vtabptr_7pymusic_EventOutputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttrString(__pyx_m, "EventOutputPort", (PyObject *)&__pyx_type_7pymusic_EventOutputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_EventOutputPort = &__pyx_type_7pymusic_EventOutputPort;
+  __pyx_vtabptr_7pymusic_MessageInputPort = &__pyx_vtable_7pymusic_MessageInputPort;
+  __pyx_vtable_7pymusic_MessageInputPort.__pyx_base = *__pyx_vtabptr_7pymusic_Port;
+  __pyx_vtable_7pymusic_MessageInputPort.__pyx_base.null = (PyObject *(*)(struct __pyx_obj_7pymusic_Port *, int __pyx_skip_dispatch))__pyx_f_7pymusic_16MessageInputPort_null;
+  __pyx_type_7pymusic_MessageInputPort.tp_base = __pyx_ptype_7pymusic_Port;
+  if (PyType_Ready(&__pyx_type_7pymusic_MessageInputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_MessageInputPort.tp_print = 0;
+  if (__Pyx_SetVtable(__pyx_type_7pymusic_MessageInputPort.tp_dict, __pyx_vtabptr_7pymusic_MessageInputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttrString(__pyx_m, "MessageInputPort", (PyObject *)&__pyx_type_7pymusic_MessageInputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_MessageInputPort = &__pyx_type_7pymusic_MessageInputPort;
+  __pyx_vtabptr_7pymusic_MessageOutputPort = &__pyx_vtable_7pymusic_MessageOutputPort;
+  __pyx_vtable_7pymusic_MessageOutputPort.__pyx_base = *__pyx_vtabptr_7pymusic_Port;
+  __pyx_type_7pymusic_MessageOutputPort.tp_base = __pyx_ptype_7pymusic_Port;
+  if (PyType_Ready(&__pyx_type_7pymusic_MessageOutputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 313; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_MessageOutputPort.tp_print = 0;
+  if (__Pyx_SetVtable(__pyx_type_7pymusic_MessageOutputPort.tp_dict, __pyx_vtabptr_7pymusic_MessageOutputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 313; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttrString(__pyx_m, "MessageOutputPort", (PyObject *)&__pyx_type_7pymusic_MessageOutputPort) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 313; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_MessageOutputPort = &__pyx_type_7pymusic_MessageOutputPort;
+  if (PyType_Ready(&__pyx_type_7pymusic_DataMap) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 585; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_DataMap.tp_print = 0;
+  if (PyObject_SetAttrString(__pyx_m, "DataMap", (PyObject *)&__pyx_type_7pymusic_DataMap) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 585; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_DataMap = &__pyx_type_7pymusic_DataMap;
+  if (PyType_Ready(&__pyx_type_7pymusic_IndexMap) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 551; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_IndexMap.tp_print = 0;
+  if (PyObject_SetAttrString(__pyx_m, "IndexMap", (PyObject *)&__pyx_type_7pymusic_IndexMap) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 551; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_IndexMap = &__pyx_type_7pymusic_IndexMap;
+  if (PyType_Ready(&__pyx_type_7pymusic_EventHandler) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 610; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_EventHandler.tp_print = 0;
+  if (PyObject_SetAttrString(__pyx_m, "EventHandler", (PyObject *)&__pyx_type_7pymusic_EventHandler) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 610; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_EventHandler = &__pyx_type_7pymusic_EventHandler;
+  if (PyType_Ready(&__pyx_type_7pymusic_MessageHandler) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 679; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic_MessageHandler.tp_print = 0;
+  if (PyObject_SetAttrString(__pyx_m, "MessageHandler", (PyObject *)&__pyx_type_7pymusic_MessageHandler) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 679; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic_MessageHandler = &__pyx_type_7pymusic_MessageHandler;
+  if (PyType_Ready(&__pyx_type_7pymusic__Index) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 636; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic__Index.tp_print = 0;
+  if (PyObject_SetAttrString(__pyx_m, "_Index", (PyObject *)&__pyx_type_7pymusic__Index) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 636; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7pymusic__Index = &__pyx_type_7pymusic__Index;
+  if (PyType_Ready(&__pyx_type_7pymusic___pyx_scope_struct____iter__) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 538; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_type_7pymusic___pyx_scope_struct____iter__.tp_print = 0;
+  __pyx_ptype_7pymusic___pyx_scope_struct____iter__ = &__pyx_type_7pymusic___pyx_scope_struct____iter__;
+  /*--- Type import code ---*/
+  __pyx_ptype_6mpi4py_3MPI_Status = __Pyx_ImportType("mpi4py.MPI", "Status", sizeof(struct PyMPIStatusObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Status)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Datatype = __Pyx_ImportType("mpi4py.MPI", "Datatype", sizeof(struct PyMPIDatatypeObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Datatype)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Request = __Pyx_ImportType("mpi4py.MPI", "Request", sizeof(struct PyMPIRequestObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Request)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Prequest = __Pyx_ImportType("mpi4py.MPI", "Prequest", sizeof(struct PyMPIPrequestObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Prequest)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Grequest = __Pyx_ImportType("mpi4py.MPI", "Grequest", sizeof(struct PyMPIGrequestObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Grequest)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Op = __Pyx_ImportType("mpi4py.MPI", "Op", sizeof(struct PyMPIOpObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Op)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Group = __Pyx_ImportType("mpi4py.MPI", "Group", sizeof(struct PyMPIGroupObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Group)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Info = __Pyx_ImportType("mpi4py.MPI", "Info", sizeof(struct PyMPIInfoObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Info)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Errhandler = __Pyx_ImportType("mpi4py.MPI", "Errhandler", sizeof(struct PyMPIErrhandlerObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Errhandler)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Comm = __Pyx_ImportType("mpi4py.MPI", "Comm", sizeof(struct PyMPICommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Comm)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Intracomm = __Pyx_ImportType("mpi4py.MPI", "Intracomm", sizeof(struct PyMPIIntracommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Intracomm)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Cartcomm = __Pyx_ImportType("mpi4py.MPI", "Cartcomm", sizeof(struct PyMPICartcommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Cartcomm)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Graphcomm = __Pyx_ImportType("mpi4py.MPI", "Graphcomm", sizeof(struct PyMPIGraphcommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Graphcomm)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Distgraphcomm = __Pyx_ImportType("mpi4py.MPI", "Distgraphcomm", sizeof(struct PyMPIDistgraphcommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Distgraphcomm)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 138; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Intercomm = __Pyx_ImportType("mpi4py.MPI", "Intercomm", sizeof(struct PyMPIIntercommObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Intercomm)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_Win = __Pyx_ImportType("mpi4py.MPI", "Win", sizeof(struct PyMPIWinObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_Win)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_6mpi4py_3MPI_File = __Pyx_ImportType("mpi4py.MPI", "File", sizeof(struct PyMPIFileObject), 1); if (unlikely(!__pyx_ptype_6mpi4py_3MPI_File)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_5music_8pybuffer_Buffer = __Pyx_ImportType("music.pybuffer", "Buffer", sizeof(struct __pyx_obj_5music_8pybuffer_Buffer), 1); if (unlikely(!__pyx_ptype_5music_8pybuffer_Buffer)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7cpython_4type_type = __Pyx_ImportType(__Pyx_BUILTIN_MODULE_NAME, "type", 
+  #if CYTHON_COMPILING_IN_PYPY
+  sizeof(PyTypeObject),
+  #else
+  sizeof(PyHeapTypeObject),
+  #endif
+  0); if (unlikely(!__pyx_ptype_7cpython_4type_type)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7cpython_4bool_bool = __Pyx_ImportType(__Pyx_BUILTIN_MODULE_NAME, "bool", sizeof(PyBoolObject), 0); if (unlikely(!__pyx_ptype_7cpython_4bool_bool)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7cpython_7complex_complex = __Pyx_ImportType(__Pyx_BUILTIN_MODULE_NAME, "complex", sizeof(PyComplexObject), 0); if (unlikely(!__pyx_ptype_7cpython_7complex_complex)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_7cpython_5array_array = __Pyx_ImportType("array", "array", sizeof(arrayobject), 0); if (unlikely(!__pyx_ptype_7cpython_5array_array)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  /*--- Variable import code ---*/
+  /*--- Function import code ---*/
+  /*--- Execution code ---*/
+
+  /* "pymusic.pyx":7
+ * from libc.stdlib cimport malloc, free
+ * 
+ * import mpi4py.MPI as MPI             # <<<<<<<<<<<<<<
+ * import cPickle as pickle
+ * 
+ */
+  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_n_s__3);
+  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s__3);
+  __Pyx_GIVEREF(__pyx_n_s__3);
+  __pyx_t_2 = __Pyx_Import(__pyx_n_s_mpi4py_MPI, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_MPI, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":8
+ * 
+ * import mpi4py.MPI as MPI
+ * import cPickle as pickle             # <<<<<<<<<<<<<<
+ * 
+ * ###########################################################
+ */
+  __pyx_t_2 = __Pyx_Import(__pyx_n_s_cPickle, 0, -1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_pickle, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":12
+ * ###########################################################
+ * 
+ * class MUSICError(Exception):             # <<<<<<<<<<<<<<
+ *     """
+ *     All exceptions in pymusic are MUSICError's
+ */
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(__pyx_builtin_Exception);
+  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_builtin_Exception);
+  __Pyx_GIVEREF(__pyx_builtin_Exception);
+  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_MUSICError, __pyx_n_s_MUSICError, (PyObject *) NULL, __pyx_n_s_pymusic, __pyx_kp_s_All_exceptions_in_pymusic_are_M); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_MUSICError, __pyx_t_2, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_MUSICError, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":18
+ *     pass
+ * 
+ * class NoWidth(MUSICError):             # <<<<<<<<<<<<<<
+ *     """
+ *     Thrown if Port.width() is called, and port doesn't
+ */
+  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_MUSICError); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = __Pyx_CalculateMetaclass(NULL, __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_2, __pyx_t_1, __pyx_n_s_NoWidth, __pyx_n_s_NoWidth, (PyObject *) NULL, __pyx_n_s_pymusic, __pyx_kp_s_Thrown_if_Port_width_is_called); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+
+  /* "pymusic.pyx":23
+ *     have a width defined.
+ *     """
+ *     def __init__(self):             # <<<<<<<<<<<<<<
+ *         MUSICError.__init__(self, "No width defined")
+ * 
+ */
+  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_7pymusic_7NoWidth_1__init__, 0, __pyx_n_s_NoWidth___init, NULL, __pyx_n_s_pymusic, __pyx_d, ((PyObject *)__pyx_codeobj__5)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  if (PyObject_SetItem(__pyx_t_3, __pyx_n_s_init, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+
+  /* "pymusic.pyx":18
+ *     pass
+ * 
+ * class NoWidth(MUSICError):             # <<<<<<<<<<<<<<
+ *     """
+ *     Thrown if Port.width() is called, and port doesn't
+ */
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_2, __pyx_n_s_NoWidth, __pyx_t_1, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_NoWidth, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":26
+ *         MUSICError.__init__(self, "No width defined")
+ * 
+ * class UndefinedConfig(MUSICError):             # <<<<<<<<<<<<<<
+ *     """
+ *     Thrown if a configuration value is requested
+ */
+  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_MUSICError); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_CalculateMetaclass(NULL, __pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __Pyx_Py3MetaclassPrepare(__pyx_t_1, __pyx_t_2, __pyx_n_s_UndefinedConfig, __pyx_n_s_UndefinedConfig, (PyObject *) NULL, __pyx_n_s_pymusic, __pyx_kp_s_Thrown_if_a_configuration_value); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+
+  /* "pymusic.pyx":32
+ *     that has not been defined within the configuration.
+ *     """
+ *     def __init__(self, var):             # <<<<<<<<<<<<<<
+ *         MUSICError.__init__(
+ *             self,
+ */
+  __pyx_t_4 = __Pyx_CyFunction_NewEx(&__pyx_mdef_7pymusic_15UndefinedConfig_1__init__, 0, __pyx_n_s_UndefinedConfig___init, NULL, __pyx_n_s_pymusic, __pyx_d, ((PyObject *)__pyx_codeobj__7)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  if (PyObject_SetItem(__pyx_t_3, __pyx_n_s_init, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+
+  /* "pymusic.pyx":26
+ *         MUSICError.__init__(self, "No width defined")
+ * 
+ * class UndefinedConfig(MUSICError):             # <<<<<<<<<<<<<<
+ *     """
+ *     Thrown if a configuration value is requested
+ */
+  __pyx_t_4 = __Pyx_Py3ClassCreate(__pyx_t_1, __pyx_n_s_UndefinedConfig, __pyx_t_2, __pyx_t_3, NULL, 0, 1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_UndefinedConfig, __pyx_t_4) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":79
+ * ###########################################################
+ * 
+ * def predictRank(list argv=None):             # <<<<<<<<<<<<<<
+ *     """
+ *     Map into mpidep/predict_rank for config methods.
+ */
+  __pyx_t_2 = PyCFunction_NewEx(&__pyx_mdef_7pymusic_1predictRank, NULL, __pyx_n_s_pymusic); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_predictRank, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":347
+ * ###########################################################
+ * 
+ * import sys             # <<<<<<<<<<<<<<
+ * cdef class Setup(object):
+ *     """
+ */
+  __pyx_t_2 = __Pyx_Import(__pyx_n_s_sys, 0, -1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_sys, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":546
+ * ###########################################################
+ * 
+ * from music.pybuffer import Buffer             # <<<<<<<<<<<<<<
+ * 
+ * from cpython cimport array
+ */
+  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 546; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(__pyx_n_s_Buffer);
+  PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_Buffer);
+  __Pyx_GIVEREF(__pyx_n_s_Buffer);
+  __pyx_t_1 = __Pyx_Import(__pyx_n_s_music_pybuffer, __pyx_t_2, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 546; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "pymusic.pyx":549
+ * 
+ * from cpython cimport array
+ * from array import array             # <<<<<<<<<<<<<<
+ * 
+ * cdef class IndexMap:
+ */
+  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 549; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_n_s_array);
+  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_array);
+  __Pyx_GIVEREF(__pyx_n_s_array);
+  __pyx_t_2 = __Pyx_Import(__pyx_n_s_array, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 549; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_array); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 549; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_array, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 549; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":662
+ * 
+ * # And here is the singleton def
+ * Index = _Index()             # <<<<<<<<<<<<<<
+ * 
+ * cdef cbool EventCallback(PyObject* func,
+ */
+  __pyx_t_2 = __Pyx_PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_7pymusic__Index)), __pyx_empty_tuple, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 662; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_Index, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 662; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "pymusic.pyx":725
+ * #    so that it can be thrown
+ * #
+ * pythonError = False             # <<<<<<<<<<<<<<
+ * etype = NULL
+ * evalue = NULL
+ */
+  MUSIC::pythonError = 0;
+
+  /* "pymusic.pyx":726
+ * #
+ * pythonError = False
+ * etype = NULL             # <<<<<<<<<<<<<<
+ * evalue = NULL
+ * etraceback = NULL
+ */
+  MUSIC::etype = NULL;
+
+  /* "pymusic.pyx":727
+ * pythonError = False
+ * etype = NULL
+ * evalue = NULL             # <<<<<<<<<<<<<<
+ * etraceback = NULL
+ */
+  MUSIC::evalue = NULL;
+
+  /* "pymusic.pyx":728
+ * etype = NULL
+ * evalue = NULL
+ * etraceback = NULL             # <<<<<<<<<<<<<<
+ */
+  MUSIC::etraceback = NULL;
+
+  /* "pymusic.pyx":1
+ * #             # <<<<<<<<<<<<<<
+ * # distutils: language = c++
+ * # cython: c_string_encoding = default
+ */
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "string.to_py":45
+ * 
+ * @cname("__pyx_convert_PyByteArray_string_to_py_std__string")
+ * cdef inline object __pyx_convert_PyByteArray_string_to_py_std__string(const string& s):             # <<<<<<<<<<<<<<
+ *     return __Pyx_PyByteArray_FromStringAndSize(s.data(), s.size())
+ * 
+ */
+
+  /*--- Wrapped vars code ---*/
+
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  if (__pyx_m) {
+    if (__pyx_d) {
+      __Pyx_AddTraceback("init pymusic", __pyx_clineno, __pyx_lineno, __pyx_filename);
+    }
+    Py_DECREF(__pyx_m); __pyx_m = 0;
+  } else if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_ImportError, "init pymusic");
+  }
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  #if PY_MAJOR_VERSION < 3
+  return;
+  #else
+  return __pyx_m;
+  #endif
+}
+
+/* Runtime support code */
+#if CYTHON_REFNANNY
+static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
+    PyObject *m = NULL, *p = NULL;
+    void *r = NULL;
+    m = PyImport_ImportModule((char *)modname);
+    if (!m) goto end;
+    p = PyObject_GetAttrString(m, (char *)"RefNannyAPI");
+    if (!p) goto end;
+    r = PyLong_AsVoidPtr(p);
+end:
+    Py_XDECREF(p);
+    Py_XDECREF(m);
+    return (__Pyx_RefNannyAPIStruct *)r;
+}
+#endif
+
+static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
+    PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name);
+    if (unlikely(!result)) {
+        PyErr_Format(PyExc_NameError,
+#if PY_MAJOR_VERSION >= 3
+            "name '%U' is not defined", name);
+#else
+            "name '%.200s' is not defined", PyString_AS_STRING(name));
+#endif
+    }
+    return result;
+}
+
+static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) {
+    PyObject *result;
+#if CYTHON_COMPILING_IN_CPYTHON
+    result = PyDict_GetItem(__pyx_d, name);
+    if (likely(result)) {
+        Py_INCREF(result);
+    } else {
+#else
+    result = PyObject_GetItem(__pyx_d, name);
+    if (!result) {
+        PyErr_Clear();
+#endif
+        result = __Pyx_GetBuiltinName(name);
+    }
+    return result;
+}
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) {
+    PyObject *result;
+    ternaryfunc call = func->ob_type->tp_call;
+    if (unlikely(!call))
+        return PyObject_Call(func, arg, kw);
+    if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object")))
+        return NULL;
+    result = (*call)(func, arg, kw);
+    Py_LeaveRecursiveCall();
+    if (unlikely(!result) && unlikely(!PyErr_Occurred())) {
+        PyErr_SetString(
+            PyExc_SystemError,
+            "NULL result without error in PyObject_Call");
+    }
+    return result;
+}
+#endif
+
+static void __Pyx_RaiseArgtupleInvalid(
+    const char* func_name,
+    int exact,
+    Py_ssize_t num_min,
+    Py_ssize_t num_max,
+    Py_ssize_t num_found)
+{
+    Py_ssize_t num_expected;
+    const char *more_or_less;
+    if (num_found < num_min) {
+        num_expected = num_min;
+        more_or_less = "at least";
+    } else {
+        num_expected = num_max;
+        more_or_less = "at most";
+    }
+    if (exact) {
+        more_or_less = "exactly";
+    }
+    PyErr_Format(PyExc_TypeError,
+                 "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)",
+                 func_name, more_or_less, num_expected,
+                 (num_expected == 1) ? "" : "s", num_found);
+}
+
+static void __Pyx_RaiseDoubleKeywordsError(
+    const char* func_name,
+    PyObject* kw_name)
+{
+    PyErr_Format(PyExc_TypeError,
+        #if PY_MAJOR_VERSION >= 3
+        "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
+        #else
+        "%s() got multiple values for keyword argument '%s'", func_name,
+        PyString_AsString(kw_name));
+        #endif
+}
+
+static int __Pyx_ParseOptionalKeywords(
+    PyObject *kwds,
+    PyObject **argnames[],
+    PyObject *kwds2,
+    PyObject *values[],
+    Py_ssize_t num_pos_args,
+    const char* function_name)
+{
+    PyObject *key = 0, *value = 0;
+    Py_ssize_t pos = 0;
+    PyObject*** name;
+    PyObject*** first_kw_arg = argnames + num_pos_args;
+    while (PyDict_Next(kwds, &pos, &key, &value)) {
+        name = first_kw_arg;
+        while (*name && (**name != key)) name++;
+        if (*name) {
+            values[name-argnames] = value;
+            continue;
+        }
+        name = first_kw_arg;
+        #if PY_MAJOR_VERSION < 3
+        if (likely(PyString_CheckExact(key)) || likely(PyString_Check(key))) {
+            while (*name) {
+                if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key))
+                        && _PyString_Eq(**name, key)) {
+                    values[name-argnames] = value;
+                    break;
+                }
+                name++;
+            }
+            if (*name) continue;
+            else {
+                PyObject*** argname = argnames;
+                while (argname != first_kw_arg) {
+                    if ((**argname == key) || (
+                            (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key))
+                             && _PyString_Eq(**argname, key))) {
+                        goto arg_passed_twice;
+                    }
+                    argname++;
+                }
+            }
+        } else
+        #endif
+        if (likely(PyUnicode_Check(key))) {
+            while (*name) {
+                int cmp = (**name == key) ? 0 :
+                #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
+                    (PyUnicode_GET_SIZE(**name) != PyUnicode_GET_SIZE(key)) ? 1 :
+                #endif
+                    PyUnicode_Compare(**name, key);
+                if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
+                if (cmp == 0) {
+                    values[name-argnames] = value;
+                    break;
+                }
+                name++;
+            }
+            if (*name) continue;
+            else {
+                PyObject*** argname = argnames;
+                while (argname != first_kw_arg) {
+                    int cmp = (**argname == key) ? 0 :
+                    #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3
+                        (PyUnicode_GET_SIZE(**argname) != PyUnicode_GET_SIZE(key)) ? 1 :
+                    #endif
+                        PyUnicode_Compare(**argname, key);
+                    if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
+                    if (cmp == 0) goto arg_passed_twice;
+                    argname++;
+                }
+            }
+        } else
+            goto invalid_keyword_type;
+        if (kwds2) {
+            if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
+        } else {
+            goto invalid_keyword;
+        }
+    }
+    return 0;
+arg_passed_twice:
+    __Pyx_RaiseDoubleKeywordsError(function_name, key);
+    goto bad;
+invalid_keyword_type:
+    PyErr_Format(PyExc_TypeError,
+        "%.200s() keywords must be strings", function_name);
+    goto bad;
+invalid_keyword:
+    PyErr_Format(PyExc_TypeError,
+    #if PY_MAJOR_VERSION < 3
+        "%.200s() got an unexpected keyword argument '%.200s'",
+        function_name, PyString_AsString(key));
+    #else
+        "%s() got an unexpected keyword argument '%U'",
+        function_name, key);
+    #endif
+bad:
+    return -1;
+}
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) {
+    PyObject *self, *result;
+    PyCFunction cfunc;
+    cfunc = PyCFunction_GET_FUNCTION(func);
+    self = PyCFunction_GET_SELF(func);
+    if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object")))
+        return NULL;
+    result = cfunc(self, arg);
+    Py_LeaveRecursiveCall();
+    if (unlikely(!result) && unlikely(!PyErr_Occurred())) {
+        PyErr_SetString(
+            PyExc_SystemError,
+            "NULL result without error in PyObject_Call");
+    }
+    return result;
+}
+#endif
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) {
+    PyObject *result;
+    PyObject *args = PyTuple_New(1);
+    if (unlikely(!args)) return NULL;
+    Py_INCREF(arg);
+    PyTuple_SET_ITEM(args, 0, arg);
+    result = __Pyx_PyObject_Call(func, args, NULL);
+    Py_DECREF(args);
+    return result;
+}
+static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) {
+#ifdef __Pyx_CyFunction_USED
+    if (likely(PyCFunction_Check(func) || PyObject_TypeCheck(func, __pyx_CyFunctionType))) {
+#else
+    if (likely(PyCFunction_Check(func))) {
+#endif
+        if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) {
+            return __Pyx_PyObject_CallMethO(func, arg);
+        }
+    }
+    return __Pyx__PyObject_CallOneArg(func, arg);
+}
+#else
+static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) {
+    PyObject* args = PyTuple_Pack(1, arg);
+    return (likely(args)) ? __Pyx_PyObject_Call(func, args, NULL) : NULL;
+}
+#endif
+
+static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+    PyThreadState *tstate = PyThreadState_GET();
+    tmp_type = tstate->curexc_type;
+    tmp_value = tstate->curexc_value;
+    tmp_tb = tstate->curexc_traceback;
+    tstate->curexc_type = type;
+    tstate->curexc_value = value;
+    tstate->curexc_traceback = tb;
+    Py_XDECREF(tmp_type);
+    Py_XDECREF(tmp_value);
+    Py_XDECREF(tmp_tb);
+#else
+    PyErr_Restore(type, value, tb);
+#endif
+}
+static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyThreadState *tstate = PyThreadState_GET();
+    *type = tstate->curexc_type;
+    *value = tstate->curexc_value;
+    *tb = tstate->curexc_traceback;
+    tstate->curexc_type = 0;
+    tstate->curexc_value = 0;
+    tstate->curexc_traceback = 0;
+#else
+    PyErr_Fetch(type, value, tb);
+#endif
+}
+
+#if PY_MAJOR_VERSION < 3
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
+                        CYTHON_UNUSED PyObject *cause) {
+    Py_XINCREF(type);
+    if (!value || value == Py_None)
+        value = NULL;
+    else
+        Py_INCREF(value);
+    if (!tb || tb == Py_None)
+        tb = NULL;
+    else {
+        Py_INCREF(tb);
+        if (!PyTraceBack_Check(tb)) {
+            PyErr_SetString(PyExc_TypeError,
+                "raise: arg 3 must be a traceback or None");
+            goto raise_error;
+        }
+    }
+    if (PyType_Check(type)) {
+#if CYTHON_COMPILING_IN_PYPY
+        if (!value) {
+            Py_INCREF(Py_None);
+            value = Py_None;
+        }
+#endif
+        PyErr_NormalizeException(&type, &value, &tb);
+    } else {
+        if (value) {
+            PyErr_SetString(PyExc_TypeError,
+                "instance exception may not have a separate value");
+            goto raise_error;
+        }
+        value = type;
+        type = (PyObject*) Py_TYPE(type);
+        Py_INCREF(type);
+        if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
+            PyErr_SetString(PyExc_TypeError,
+                "raise: exception class must be a subclass of BaseException");
+            goto raise_error;
+        }
+    }
+    __Pyx_ErrRestore(type, value, tb);
+    return;
+raise_error:
+    Py_XDECREF(value);
+    Py_XDECREF(type);
+    Py_XDECREF(tb);
+    return;
+}
+#else
+static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
+    PyObject* owned_instance = NULL;
+    if (tb == Py_None) {
+        tb = 0;
+    } else if (tb && !PyTraceBack_Check(tb)) {
+        PyErr_SetString(PyExc_TypeError,
+            "raise: arg 3 must be a traceback or None");
+        goto bad;
+    }
+    if (value == Py_None)
+        value = 0;
+    if (PyExceptionInstance_Check(type)) {
+        if (value) {
+            PyErr_SetString(PyExc_TypeError,
+                "instance exception may not have a separate value");
+            goto bad;
+        }
+        value = type;
+        type = (PyObject*) Py_TYPE(value);
+    } else if (PyExceptionClass_Check(type)) {
+        PyObject *instance_class = NULL;
+        if (value && PyExceptionInstance_Check(value)) {
+            instance_class = (PyObject*) Py_TYPE(value);
+            if (instance_class != type) {
+                if (PyObject_IsSubclass(instance_class, type)) {
+                    type = instance_class;
+                } else {
+                    instance_class = NULL;
+                }
+            }
+        }
+        if (!instance_class) {
+            PyObject *args;
+            if (!value)
+                args = PyTuple_New(0);
+            else if (PyTuple_Check(value)) {
+                Py_INCREF(value);
+                args = value;
+            } else
+                args = PyTuple_Pack(1, value);
+            if (!args)
+                goto bad;
+            owned_instance = PyObject_Call(type, args, NULL);
+            Py_DECREF(args);
+            if (!owned_instance)
+                goto bad;
+            value = owned_instance;
+            if (!PyExceptionInstance_Check(value)) {
+                PyErr_Format(PyExc_TypeError,
+                             "calling %R should have returned an instance of "
+                             "BaseException, not %R",
+                             type, Py_TYPE(value));
+                goto bad;
+            }
+        }
+    } else {
+        PyErr_SetString(PyExc_TypeError,
+            "raise: exception class must be a subclass of BaseException");
+        goto bad;
+    }
+#if PY_VERSION_HEX >= 0x03030000
+    if (cause) {
+#else
+    if (cause && cause != Py_None) {
+#endif
+        PyObject *fixed_cause;
+        if (cause == Py_None) {
+            fixed_cause = NULL;
+        } else if (PyExceptionClass_Check(cause)) {
+            fixed_cause = PyObject_CallObject(cause, NULL);
+            if (fixed_cause == NULL)
+                goto bad;
+        } else if (PyExceptionInstance_Check(cause)) {
+            fixed_cause = cause;
+            Py_INCREF(fixed_cause);
+        } else {
+            PyErr_SetString(PyExc_TypeError,
+                            "exception causes must derive from "
+                            "BaseException");
+            goto bad;
+        }
+        PyException_SetCause(value, fixed_cause);
+    }
+    PyErr_SetObject(type, value);
+    if (tb) {
+#if CYTHON_COMPILING_IN_PYPY
+        PyObject *tmp_type, *tmp_value, *tmp_tb;
+        PyErr_Fetch(tmp_type, tmp_value, tmp_tb);
+        Py_INCREF(tb);
+        PyErr_Restore(tmp_type, tmp_value, tb);
+        Py_XDECREF(tmp_tb);
+#else
+        PyThreadState *tstate = PyThreadState_GET();
+        PyObject* tmp_tb = tstate->curexc_traceback;
+        if (tb != tmp_tb) {
+            Py_INCREF(tb);
+            tstate->curexc_traceback = tb;
+            Py_XDECREF(tmp_tb);
+        }
+#endif
+    }
+bad:
+    Py_XDECREF(owned_instance);
+    return;
+}
+#endif
+
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
+    PyObject *r;
+    if (!j) return NULL;
+    r = PyObject_GetItem(o, j);
+    Py_DECREF(j);
+    return r;
+}
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    if (wraparound & unlikely(i < 0)) i += PyList_GET_SIZE(o);
+    if ((!boundscheck) || likely((0 <= i) & (i < PyList_GET_SIZE(o)))) {
+        PyObject *r = PyList_GET_ITEM(o, i);
+        Py_INCREF(r);
+        return r;
+    }
+    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
+#else
+    return PySequence_GetItem(o, i);
+#endif
+}
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    if (wraparound & unlikely(i < 0)) i += PyTuple_GET_SIZE(o);
+    if ((!boundscheck) || likely((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
+        PyObject *r = PyTuple_GET_ITEM(o, i);
+        Py_INCREF(r);
+        return r;
+    }
+    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
+#else
+    return PySequence_GetItem(o, i);
+#endif
+}
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
+                                                     int is_list, int wraparound, int boundscheck) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    if (is_list || PyList_CheckExact(o)) {
+        Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o);
+        if ((!boundscheck) || (likely((n >= 0) & (n < PyList_GET_SIZE(o))))) {
+            PyObject *r = PyList_GET_ITEM(o, n);
+            Py_INCREF(r);
+            return r;
+        }
+    }
+    else if (PyTuple_CheckExact(o)) {
+        Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o);
+        if ((!boundscheck) || likely((n >= 0) & (n < PyTuple_GET_SIZE(o)))) {
+            PyObject *r = PyTuple_GET_ITEM(o, n);
+            Py_INCREF(r);
+            return r;
+        }
+    } else {
+        PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
+        if (likely(m && m->sq_item)) {
+            if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
+                Py_ssize_t l = m->sq_length(o);
+                if (likely(l >= 0)) {
+                    i += l;
+                } else {
+                    if (PyErr_ExceptionMatches(PyExc_OverflowError))
+                        PyErr_Clear();
+                    else
+                        return NULL;
+                }
+            }
+            return m->sq_item(o, i);
+        }
+    }
+#else
+    if (is_list || PySequence_Check(o)) {
+        return PySequence_GetItem(o, i);
+    }
+#endif
+    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
+}
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
+#ifdef __Pyx_CyFunction_USED
+    if (likely(PyCFunction_Check(func) || PyObject_TypeCheck(func, __pyx_CyFunctionType))) {
+#else
+    if (likely(PyCFunction_Check(func))) {
+#endif
+        if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) {
+            return __Pyx_PyObject_CallMethO(func, NULL);
+        }
+    }
+    return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL);
+}
+#endif
+
+static CYTHON_INLINE void __Pyx_ExceptionSave(PyObject **type, PyObject **value, PyObject **tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyThreadState *tstate = PyThreadState_GET();
+    *type = tstate->exc_type;
+    *value = tstate->exc_value;
+    *tb = tstate->exc_traceback;
+    Py_XINCREF(*type);
+    Py_XINCREF(*value);
+    Py_XINCREF(*tb);
+#else
+    PyErr_GetExcInfo(type, value, tb);
+#endif
+}
+static void __Pyx_ExceptionReset(PyObject *type, PyObject *value, PyObject *tb) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+    PyThreadState *tstate = PyThreadState_GET();
+    tmp_type = tstate->exc_type;
+    tmp_value = tstate->exc_value;
+    tmp_tb = tstate->exc_traceback;
+    tstate->exc_type = type;
+    tstate->exc_value = value;
+    tstate->exc_traceback = tb;
+    Py_XDECREF(tmp_type);
+    Py_XDECREF(tmp_value);
+    Py_XDECREF(tmp_tb);
+#else
+    PyErr_SetExcInfo(type, value, tb);
+#endif
+}
+
+static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb) {
+    PyObject *local_type, *local_value, *local_tb;
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+    PyThreadState *tstate = PyThreadState_GET();
+    local_type = tstate->curexc_type;
+    local_value = tstate->curexc_value;
+    local_tb = tstate->curexc_traceback;
+    tstate->curexc_type = 0;
+    tstate->curexc_value = 0;
+    tstate->curexc_traceback = 0;
+#else
+    PyErr_Fetch(&local_type, &local_value, &local_tb);
+#endif
+    PyErr_NormalizeException(&local_type, &local_value, &local_tb);
+#if CYTHON_COMPILING_IN_CPYTHON
+    if (unlikely(tstate->curexc_type))
+#else
+    if (unlikely(PyErr_Occurred()))
+#endif
+        goto bad;
+    #if PY_MAJOR_VERSION >= 3
+    if (local_tb) {
+        if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
+            goto bad;
+    }
+    #endif
+    Py_XINCREF(local_tb);
+    Py_XINCREF(local_type);
+    Py_XINCREF(local_value);
+    *type = local_type;
+    *value = local_value;
+    *tb = local_tb;
+#if CYTHON_COMPILING_IN_CPYTHON
+    tmp_type = tstate->exc_type;
+    tmp_value = tstate->exc_value;
+    tmp_tb = tstate->exc_traceback;
+    tstate->exc_type = local_type;
+    tstate->exc_value = local_value;
+    tstate->exc_traceback = local_tb;
+    Py_XDECREF(tmp_type);
+    Py_XDECREF(tmp_value);
+    Py_XDECREF(tmp_tb);
+#else
+    PyErr_SetExcInfo(local_type, local_value, local_tb);
+#endif
+    return 0;
+bad:
+    *type = 0;
+    *value = 0;
+    *tb = 0;
+    Py_XDECREF(local_type);
+    Py_XDECREF(local_value);
+    Py_XDECREF(local_tb);
+    return -1;
+}
+
+static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno,
+                                  CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename,
+                                  int full_traceback) {
+    PyObject *old_exc, *old_val, *old_tb;
+    PyObject *ctx;
+    __Pyx_ErrFetch(&old_exc, &old_val, &old_tb);
+    if (full_traceback) {
+        Py_XINCREF(old_exc);
+        Py_XINCREF(old_val);
+        Py_XINCREF(old_tb);
+        __Pyx_ErrRestore(old_exc, old_val, old_tb);
+        PyErr_PrintEx(1);
+    }
+    #if PY_MAJOR_VERSION < 3
+    ctx = PyString_FromString(name);
+    #else
+    ctx = PyUnicode_FromString(name);
+    #endif
+    __Pyx_ErrRestore(old_exc, old_val, old_tb);
+    if (!ctx) {
+        PyErr_WriteUnraisable(Py_None);
+    } else {
+        PyErr_WriteUnraisable(ctx);
+        Py_DECREF(ctx);
+    }
+}
+
+static void __Pyx_RaiseArgumentTypeInvalid(const char* name, PyObject *obj, PyTypeObject *type) {
+    PyErr_Format(PyExc_TypeError,
+        "Argument '%.200s' has incorrect type (expected %.200s, got %.200s)",
+        name, type->tp_name, Py_TYPE(obj)->tp_name);
+}
+static CYTHON_INLINE int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
+    const char *name, int exact)
+{
+    if (unlikely(!type)) {
+        PyErr_SetString(PyExc_SystemError, "Missing type object");
+        return 0;
+    }
+    if (none_allowed && obj == Py_None) return 1;
+    else if (exact) {
+        if (likely(Py_TYPE(obj) == type)) return 1;
+        #if PY_MAJOR_VERSION == 2
+        else if ((type == &PyBaseString_Type) && likely(__Pyx_PyBaseString_CheckExact(obj))) return 1;
+        #endif
+    }
+    else {
+        if (likely(PyObject_TypeCheck(obj, type))) return 1;
+    }
+    __Pyx_RaiseArgumentTypeInvalid(name, obj, type);
+    return 0;
+}
+
+static CYTHON_INLINE int __Pyx_CheckKeywordStrings(
+    PyObject *kwdict,
+    const char* function_name,
+    int kw_allowed)
+{
+    PyObject* key = 0;
+    Py_ssize_t pos = 0;
+#if CYTHON_COMPILING_IN_PYPY
+    if (!kw_allowed && PyDict_Next(kwdict, &pos, &key, 0))
+        goto invalid_keyword;
+    return 1;
+#else
+    while (PyDict_Next(kwdict, &pos, &key, 0)) {
+        #if PY_MAJOR_VERSION < 3
+        if (unlikely(!PyString_CheckExact(key)) && unlikely(!PyString_Check(key)))
+        #endif
+            if (unlikely(!PyUnicode_Check(key)))
+                goto invalid_keyword_type;
+    }
+    if ((!kw_allowed) && unlikely(key))
+        goto invalid_keyword;
+    return 1;
+invalid_keyword_type:
+    PyErr_Format(PyExc_TypeError,
+        "%.200s() keywords must be strings", function_name);
+    return 0;
+#endif
+invalid_keyword:
+    PyErr_Format(PyExc_TypeError,
+    #if PY_MAJOR_VERSION < 3
+        "%.200s() got an unexpected keyword argument '%.200s'",
+        function_name, PyString_AsString(key));
+    #else
+        "%s() got an unexpected keyword argument '%U'",
+        function_name, key);
+    #endif
+    return 0;
+}
+
+static CYTHON_INLINE void __Pyx_ExceptionSwap(PyObject **type, PyObject **value, PyObject **tb) {
+    PyObject *tmp_type, *tmp_value, *tmp_tb;
+#if CYTHON_COMPILING_IN_CPYTHON
+    PyThreadState *tstate = PyThreadState_GET();
+    tmp_type = tstate->exc_type;
+    tmp_value = tstate->exc_value;
+    tmp_tb = tstate->exc_traceback;
+    tstate->exc_type = *type;
+    tstate->exc_value = *value;
+    tstate->exc_traceback = *tb;
+#else
+    PyErr_GetExcInfo(&tmp_type, &tmp_value, &tmp_tb);
+    PyErr_SetExcInfo(*type, *value, *tb);
+#endif
+    *type = tmp_type;
+    *value = tmp_value;
+    *tb = tmp_tb;
+}
+
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
+    if (unlikely(!type)) {
+        PyErr_SetString(PyExc_SystemError, "Missing type object");
+        return 0;
+    }
+    if (likely(PyObject_TypeCheck(obj, type)))
+        return 1;
+    PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
+                 Py_TYPE(obj)->tp_name, type->tp_name);
+    return 0;
+}
+
+static double __Pyx__PyObject_AsDouble(PyObject* obj) {
+    PyObject* float_value;
+#if CYTHON_COMPILING_IN_PYPY
+    float_value = PyNumber_Float(obj);
+#else
+    PyNumberMethods *nb = Py_TYPE(obj)->tp_as_number;
+    if (likely(nb) && likely(nb->nb_float)) {
+        float_value = nb->nb_float(obj);
+        if (likely(float_value) && unlikely(!PyFloat_Check(float_value))) {
+            PyErr_Format(PyExc_TypeError,
+                "__float__ returned non-float (type %.200s)",
+                Py_TYPE(float_value)->tp_name);
+            Py_DECREF(float_value);
+            goto bad;
+        }
+    } else if (PyUnicode_CheckExact(obj) || PyBytes_CheckExact(obj)) {
+#if PY_MAJOR_VERSION >= 3
+        float_value = PyFloat_FromString(obj);
+#else
+        float_value = PyFloat_FromString(obj, 0);
+#endif
+    } else {
+        PyObject* args = PyTuple_New(1);
+        if (unlikely(!args)) goto bad;
+        PyTuple_SET_ITEM(args, 0, obj);
+        float_value = PyObject_Call((PyObject*)&PyFloat_Type, args, 0);
+        PyTuple_SET_ITEM(args, 0, 0);
+        Py_DECREF(args);
+    }
+#endif
+    if (likely(float_value)) {
+        double value = PyFloat_AS_DOUBLE(float_value);
+        Py_DECREF(float_value);
+        return value;
+    }
+bad:
+    return (double)-1;
+}
+
+static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, traverseproc current_tp_traverse) {
+    PyTypeObject* type = Py_TYPE(obj);
+    while (type && type->tp_traverse != current_tp_traverse)
+        type = type->tp_base;
+    while (type && type->tp_traverse == current_tp_traverse)
+        type = type->tp_base;
+    if (type && type->tp_traverse)
+        return type->tp_traverse(obj, v, a);
+    return 0;
+}
+
+static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear) {
+    PyTypeObject* type = Py_TYPE(obj);
+    while (type && type->tp_clear != current_tp_clear)
+        type = type->tp_base;
+    while (type && type->tp_clear == current_tp_clear)
+        type = type->tp_base;
+    if (type && type->tp_clear)
+        type->tp_clear(obj);
+}
+
+static int __Pyx_SetVtable(PyObject *dict, void *vtable) {
+#if PY_VERSION_HEX >= 0x02070000
+    PyObject *ob = PyCapsule_New(vtable, 0, 0);
+#else
+    PyObject *ob = PyCObject_FromVoidPtr(vtable, 0);
+#endif
+    if (!ob)
+        goto bad;
+    if (PyDict_SetItem(dict, __pyx_n_s_pyx_vtable, ob) < 0)
+        goto bad;
+    Py_DECREF(ob);
+    return 0;
+bad:
+    Py_XDECREF(ob);
+    return -1;
+}
+
+static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases) {
+    Py_ssize_t i, nbases = PyTuple_GET_SIZE(bases);
+    for (i=0; i < nbases; i++) {
+        PyTypeObject *tmptype;
+        PyObject *tmp = PyTuple_GET_ITEM(bases, i);
+        tmptype = Py_TYPE(tmp);
+#if PY_MAJOR_VERSION < 3
+        if (tmptype == &PyClass_Type)
+            continue;
+#endif
+        if (!metaclass) {
+            metaclass = tmptype;
+            continue;
+        }
+        if (PyType_IsSubtype(metaclass, tmptype))
+            continue;
+        if (PyType_IsSubtype(tmptype, metaclass)) {
+            metaclass = tmptype;
+            continue;
+        }
+        PyErr_SetString(PyExc_TypeError,
+                        "metaclass conflict: "
+                        "the metaclass of a derived class "
+                        "must be a (non-strict) subclass "
+                        "of the metaclasses of all its bases");
+        return NULL;
+    }
+    if (!metaclass) {
+#if PY_MAJOR_VERSION < 3
+        metaclass = &PyClass_Type;
+#else
+        metaclass = &PyType_Type;
+#endif
+    }
+    Py_INCREF((PyObject*) metaclass);
+    return (PyObject*) metaclass;
+}
+
+static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name,
+                                           PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc) {
+    PyObject *ns;
+    if (metaclass) {
+        PyObject *prep = __Pyx_PyObject_GetAttrStr(metaclass, __pyx_n_s_prepare);
+        if (prep) {
+            PyObject *pargs = PyTuple_Pack(2, name, bases);
+            if (unlikely(!pargs)) {
+                Py_DECREF(prep);
+                return NULL;
+            }
+            ns = PyObject_Call(prep, pargs, mkw);
+            Py_DECREF(prep);
+            Py_DECREF(pargs);
+        } else {
+            if (unlikely(!PyErr_ExceptionMatches(PyExc_AttributeError)))
+                return NULL;
+            PyErr_Clear();
+            ns = PyDict_New();
+        }
+    } else {
+        ns = PyDict_New();
+    }
+    if (unlikely(!ns))
+        return NULL;
+    if (unlikely(PyObject_SetItem(ns, __pyx_n_s_module, modname) < 0)) goto bad;
+    if (unlikely(PyObject_SetItem(ns, __pyx_n_s_qualname, qualname) < 0)) goto bad;
+    if (unlikely(doc && PyObject_SetItem(ns, __pyx_n_s_doc, doc) < 0)) goto bad;
+    return ns;
+bad:
+    Py_DECREF(ns);
+    return NULL;
+}
+static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases,
+                                      PyObject *dict, PyObject *mkw,
+                                      int calculate_metaclass, int allow_py2_metaclass) {
+    PyObject *result, *margs;
+    PyObject *owned_metaclass = NULL;
+    if (allow_py2_metaclass) {
+        owned_metaclass = PyObject_GetItem(dict, __pyx_n_s_metaclass);
+        if (owned_metaclass) {
+            metaclass = owned_metaclass;
+        } else if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) {
+            PyErr_Clear();
+        } else {
+            return NULL;
+        }
+    }
+    if (calculate_metaclass && (!metaclass || PyType_Check(metaclass))) {
+        metaclass = __Pyx_CalculateMetaclass((PyTypeObject*) metaclass, bases);
+        Py_XDECREF(owned_metaclass);
+        if (unlikely(!metaclass))
+            return NULL;
+        owned_metaclass = metaclass;
+    }
+    margs = PyTuple_Pack(3, name, bases, dict);
+    if (unlikely(!margs)) {
+        result = NULL;
+    } else {
+        result = PyObject_Call(metaclass, margs, mkw);
+        Py_DECREF(margs);
+    }
+    Py_XDECREF(owned_metaclass);
+    return result;
+}
+
+static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
+    PyObject* fake_module;
+    PyTypeObject* cached_type = NULL;
+    fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI);
+    if (!fake_module) return NULL;
+    Py_INCREF(fake_module);
+    cached_type = (PyTypeObject*) PyObject_GetAttrString(fake_module, type->tp_name);
+    if (cached_type) {
+        if (!PyType_Check((PyObject*)cached_type)) {
+            PyErr_Format(PyExc_TypeError,
+                "Shared Cython type %.200s is not a type object",
+                type->tp_name);
+            goto bad;
+        }
+        if (cached_type->tp_basicsize != type->tp_basicsize) {
+            PyErr_Format(PyExc_TypeError,
+                "Shared Cython type %.200s has the wrong size, try recompiling",
+                type->tp_name);
+            goto bad;
+        }
+    } else {
+        if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
+        PyErr_Clear();
+        if (PyType_Ready(type) < 0) goto bad;
+        if (PyObject_SetAttrString(fake_module, type->tp_name, (PyObject*) type) < 0)
+            goto bad;
+        Py_INCREF(type);
+        cached_type = type;
+    }
+done:
+    Py_DECREF(fake_module);
+    return cached_type;
+bad:
+    Py_XDECREF(cached_type);
+    cached_type = NULL;
+    goto done;
+}
+
+static PyObject *
+__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure)
+{
+    if (unlikely(op->func_doc == NULL)) {
+        if (op->func.m_ml->ml_doc) {
+#if PY_MAJOR_VERSION >= 3
+            op->func_doc = PyUnicode_FromString(op->func.m_ml->ml_doc);
+#else
+            op->func_doc = PyString_FromString(op->func.m_ml->ml_doc);
+#endif
+            if (unlikely(op->func_doc == NULL))
+                return NULL;
+        } else {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+    }
+    Py_INCREF(op->func_doc);
+    return op->func_doc;
+}
+static int
+__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value)
+{
+    PyObject *tmp = op->func_doc;
+    if (value == NULL) {
+        value = Py_None;
+    }
+    Py_INCREF(value);
+    op->func_doc = value;
+    Py_XDECREF(tmp);
+    return 0;
+}
+static PyObject *
+__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op)
+{
+    if (unlikely(op->func_name == NULL)) {
+#if PY_MAJOR_VERSION >= 3
+        op->func_name = PyUnicode_InternFromString(op->func.m_ml->ml_name);
+#else
+        op->func_name = PyString_InternFromString(op->func.m_ml->ml_name);
+#endif
+        if (unlikely(op->func_name == NULL))
+            return NULL;
+    }
+    Py_INCREF(op->func_name);
+    return op->func_name;
+}
+static int
+__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value)
+{
+    PyObject *tmp;
+#if PY_MAJOR_VERSION >= 3
+    if (unlikely(value == NULL || !PyUnicode_Check(value))) {
+#else
+    if (unlikely(value == NULL || !PyString_Check(value))) {
+#endif
+        PyErr_SetString(PyExc_TypeError,
+                        "__name__ must be set to a string object");
+        return -1;
+    }
+    tmp = op->func_name;
+    Py_INCREF(value);
+    op->func_name = value;
+    Py_XDECREF(tmp);
+    return 0;
+}
+static PyObject *
+__Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op)
+{
+    Py_INCREF(op->func_qualname);
+    return op->func_qualname;
+}
+static int
+__Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value)
+{
+    PyObject *tmp;
+#if PY_MAJOR_VERSION >= 3
+    if (unlikely(value == NULL || !PyUnicode_Check(value))) {
+#else
+    if (unlikely(value == NULL || !PyString_Check(value))) {
+#endif
+        PyErr_SetString(PyExc_TypeError,
+                        "__qualname__ must be set to a string object");
+        return -1;
+    }
+    tmp = op->func_qualname;
+    Py_INCREF(value);
+    op->func_qualname = value;
+    Py_XDECREF(tmp);
+    return 0;
+}
+static PyObject *
+__Pyx_CyFunction_get_self(__pyx_CyFunctionObject *m, CYTHON_UNUSED void *closure)
+{
+    PyObject *self;
+    self = m->func_closure;
+    if (self == NULL)
+        self = Py_None;
+    Py_INCREF(self);
+    return self;
+}
+static PyObject *
+__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op)
+{
+    if (unlikely(op->func_dict == NULL)) {
+        op->func_dict = PyDict_New();
+        if (unlikely(op->func_dict == NULL))
+            return NULL;
+    }
+    Py_INCREF(op->func_dict);
+    return op->func_dict;
+}
+static int
+__Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value)
+{
+    PyObject *tmp;
+    if (unlikely(value == NULL)) {
+        PyErr_SetString(PyExc_TypeError,
+               "function's dictionary may not be deleted");
+        return -1;
+    }
+    if (unlikely(!PyDict_Check(value))) {
+        PyErr_SetString(PyExc_TypeError,
+               "setting function's dictionary to a non-dict");
+        return -1;
+    }
+    tmp = op->func_dict;
+    Py_INCREF(value);
+    op->func_dict = value;
+    Py_XDECREF(tmp);
+    return 0;
+}
+static PyObject *
+__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op)
+{
+    Py_INCREF(op->func_globals);
+    return op->func_globals;
+}
+static PyObject *
+__Pyx_CyFunction_get_closure(CYTHON_UNUSED __pyx_CyFunctionObject *op)
+{
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+static PyObject *
+__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op)
+{
+    PyObject* result = (op->func_code) ? op->func_code : Py_None;
+    Py_INCREF(result);
+    return result;
+}
+static int
+__Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) {
+    PyObject *res = op->defaults_getter((PyObject *) op);
+    if (unlikely(!res))
+        return -1;
+    op->defaults_tuple = PyTuple_GET_ITEM(res, 0);
+    Py_INCREF(op->defaults_tuple);
+    op->defaults_kwdict = PyTuple_GET_ITEM(res, 1);
+    Py_INCREF(op->defaults_kwdict);
+    Py_DECREF(res);
+    return 0;
+}
+static int
+__Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value) {
+    PyObject* tmp;
+    if (!value) {
+        value = Py_None;
+    } else if (value != Py_None && !PyTuple_Check(value)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "__defaults__ must be set to a tuple object");
+        return -1;
+    }
+    Py_INCREF(value);
+    tmp = op->defaults_tuple;
+    op->defaults_tuple = value;
+    Py_XDECREF(tmp);
+    return 0;
+}
+static PyObject *
+__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op) {
+    PyObject* result = op->defaults_tuple;
+    if (unlikely(!result)) {
+        if (op->defaults_getter) {
+            if (__Pyx_CyFunction_init_defaults(op) < 0) return NULL;
+            result = op->defaults_tuple;
+        } else {
+            result = Py_None;
+        }
+    }
+    Py_INCREF(result);
+    return result;
+}
+static int
+__Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value) {
+    PyObject* tmp;
+    if (!value) {
+        value = Py_None;
+    } else if (value != Py_None && !PyDict_Check(value)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "__kwdefaults__ must be set to a dict object");
+        return -1;
+    }
+    Py_INCREF(value);
+    tmp = op->defaults_kwdict;
+    op->defaults_kwdict = value;
+    Py_XDECREF(tmp);
+    return 0;
+}
+static PyObject *
+__Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op) {
+    PyObject* result = op->defaults_kwdict;
+    if (unlikely(!result)) {
+        if (op->defaults_getter) {
+            if (__Pyx_CyFunction_init_defaults(op) < 0) return NULL;
+            result = op->defaults_kwdict;
+        } else {
+            result = Py_None;
+        }
+    }
+    Py_INCREF(result);
+    return result;
+}
+static int
+__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value) {
+    PyObject* tmp;
+    if (!value || value == Py_None) {
+        value = NULL;
+    } else if (!PyDict_Check(value)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "__annotations__ must be set to a dict object");
+        return -1;
+    }
+    Py_XINCREF(value);
+    tmp = op->func_annotations;
+    op->func_annotations = value;
+    Py_XDECREF(tmp);
+    return 0;
+}
+static PyObject *
+__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op) {
+    PyObject* result = op->func_annotations;
+    if (unlikely(!result)) {
+        result = PyDict_New();
+        if (unlikely(!result)) return NULL;
+        op->func_annotations = result;
+    }
+    Py_INCREF(result);
+    return result;
+}
+static PyGetSetDef __pyx_CyFunction_getsets[] = {
+    {(char *) "func_doc", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
+    {(char *) "__doc__",  (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
+    {(char *) "func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
+    {(char *) "__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
+    {(char *) "__qualname__", (getter)__Pyx_CyFunction_get_qualname, (setter)__Pyx_CyFunction_set_qualname, 0, 0},
+    {(char *) "__self__", (getter)__Pyx_CyFunction_get_self, 0, 0, 0},
+    {(char *) "func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0},
+    {(char *) "__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0},
+    {(char *) "func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0},
+    {(char *) "__globals__", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0},
+    {(char *) "func_closure", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0},
+    {(char *) "__closure__", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0},
+    {(char *) "func_code", (getter)__Pyx_CyFunction_get_code, 0, 0, 0},
+    {(char *) "__code__", (getter)__Pyx_CyFunction_get_code, 0, 0, 0},
+    {(char *) "func_defaults", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0},
+    {(char *) "__defaults__", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0},
+    {(char *) "__kwdefaults__", (getter)__Pyx_CyFunction_get_kwdefaults, (setter)__Pyx_CyFunction_set_kwdefaults, 0, 0},
+    {(char *) "__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0},
+    {0, 0, 0, 0, 0}
+};
+#ifndef PY_WRITE_RESTRICTED
+#define PY_WRITE_RESTRICTED WRITE_RESTRICTED
+#endif
+static PyMemberDef __pyx_CyFunction_members[] = {
+    {(char *) "__module__", T_OBJECT, offsetof(__pyx_CyFunctionObject, func.m_module), PY_WRITE_RESTRICTED, 0},
+    {0, 0, 0,  0, 0}
+};
+static PyObject *
+__Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, CYTHON_UNUSED PyObject *args)
+{
+#if PY_MAJOR_VERSION >= 3
+    return PyUnicode_FromString(m->func.m_ml->ml_name);
+#else
+    return PyString_FromString(m->func.m_ml->ml_name);
+#endif
+}
+static PyMethodDef __pyx_CyFunction_methods[] = {
+    {"__reduce__", (PyCFunction)__Pyx_CyFunction_reduce, METH_VARARGS, 0},
+    {0, 0, 0, 0}
+};
+#if PY_VERSION_HEX < 0x030500A0
+#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func_weakreflist)
+#else
+#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func.m_weakreflist)
+#endif
+static PyObject *__Pyx_CyFunction_New(PyTypeObject *type, PyMethodDef *ml, int flags, PyObject* qualname,
+                                      PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) {
+    __pyx_CyFunctionObject *op = PyObject_GC_New(__pyx_CyFunctionObject, type);
+    if (op == NULL)
+        return NULL;
+    op->flags = flags;
+    __Pyx_CyFunction_weakreflist(op) = NULL;
+    op->func.m_ml = ml;
+    op->func.m_self = (PyObject *) op;
+    Py_XINCREF(closure);
+    op->func_closure = closure;
+    Py_XINCREF(module);
+    op->func.m_module = module;
+    op->func_dict = NULL;
+    op->func_name = NULL;
+    Py_INCREF(qualname);
+    op->func_qualname = qualname;
+    op->func_doc = NULL;
+    op->func_classobj = NULL;
+    op->func_globals = globals;
+    Py_INCREF(op->func_globals);
+    Py_XINCREF(code);
+    op->func_code = code;
+    op->defaults_pyobjects = 0;
+    op->defaults = NULL;
+    op->defaults_tuple = NULL;
+    op->defaults_kwdict = NULL;
+    op->defaults_getter = NULL;
+    op->func_annotations = NULL;
+    PyObject_GC_Track(op);
+    return (PyObject *) op;
+}
+static int
+__Pyx_CyFunction_clear(__pyx_CyFunctionObject *m)
+{
+    Py_CLEAR(m->func_closure);
+    Py_CLEAR(m->func.m_module);
+    Py_CLEAR(m->func_dict);
+    Py_CLEAR(m->func_name);
+    Py_CLEAR(m->func_qualname);
+    Py_CLEAR(m->func_doc);
+    Py_CLEAR(m->func_globals);
+    Py_CLEAR(m->func_code);
+    Py_CLEAR(m->func_classobj);
+    Py_CLEAR(m->defaults_tuple);
+    Py_CLEAR(m->defaults_kwdict);
+    Py_CLEAR(m->func_annotations);
+    if (m->defaults) {
+        PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m);
+        int i;
+        for (i = 0; i < m->defaults_pyobjects; i++)
+            Py_XDECREF(pydefaults[i]);
+        PyMem_Free(m->defaults);
+        m->defaults = NULL;
+    }
+    return 0;
+}
+static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m)
+{
+    PyObject_GC_UnTrack(m);
+    if (__Pyx_CyFunction_weakreflist(m) != NULL)
+        PyObject_ClearWeakRefs((PyObject *) m);
+    __Pyx_CyFunction_clear(m);
+    PyObject_GC_Del(m);
+}
+static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, void *arg)
+{
+    Py_VISIT(m->func_closure);
+    Py_VISIT(m->func.m_module);
+    Py_VISIT(m->func_dict);
+    Py_VISIT(m->func_name);
+    Py_VISIT(m->func_qualname);
+    Py_VISIT(m->func_doc);
+    Py_VISIT(m->func_globals);
+    Py_VISIT(m->func_code);
+    Py_VISIT(m->func_classobj);
+    Py_VISIT(m->defaults_tuple);
+    Py_VISIT(m->defaults_kwdict);
+    if (m->defaults) {
+        PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m);
+        int i;
+        for (i = 0; i < m->defaults_pyobjects; i++)
+            Py_VISIT(pydefaults[i]);
+    }
+    return 0;
+}
+static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type)
+{
+    __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
+    if (m->flags & __Pyx_CYFUNCTION_STATICMETHOD) {
+        Py_INCREF(func);
+        return func;
+    }
+    if (m->flags & __Pyx_CYFUNCTION_CLASSMETHOD) {
+        if (type == NULL)
+            type = (PyObject *)(Py_TYPE(obj));
+        return __Pyx_PyMethod_New(func, type, (PyObject *)(Py_TYPE(type)));
+    }
+    if (obj == Py_None)
+        obj = NULL;
+    return __Pyx_PyMethod_New(func, obj, type);
+}
+static PyObject*
+__Pyx_CyFunction_repr(__pyx_CyFunctionObject *op)
+{
+#if PY_MAJOR_VERSION >= 3
+    return PyUnicode_FromFormat("<cyfunction %U at %p>",
+                                op->func_qualname, (void *)op);
+#else
+    return PyString_FromFormat("<cyfunction %s at %p>",
+                               PyString_AsString(op->func_qualname), (void *)op);
+#endif
+}
+#if CYTHON_COMPILING_IN_PYPY
+static PyObject * __Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) {
+    PyCFunctionObject* f = (PyCFunctionObject*)func;
+    PyCFunction meth = PyCFunction_GET_FUNCTION(func);
+    PyObject *self = PyCFunction_GET_SELF(func);
+    Py_ssize_t size;
+    switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
+    case METH_VARARGS:
+        if (likely(kw == NULL) || PyDict_Size(kw) == 0)
+            return (*meth)(self, arg);
+        break;
+    case METH_VARARGS | METH_KEYWORDS:
+        return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
+    case METH_NOARGS:
+        if (likely(kw == NULL) || PyDict_Size(kw) == 0) {
+            size = PyTuple_GET_SIZE(arg);
+            if (size == 0)
+                return (*meth)(self, NULL);
+            PyErr_Format(PyExc_TypeError,
+                "%.200s() takes no arguments (%zd given)",
+                f->m_ml->ml_name, size);
+            return NULL;
+        }
+        break;
+    case METH_O:
+        if (likely(kw == NULL) || PyDict_Size(kw) == 0) {
+            size = PyTuple_GET_SIZE(arg);
+            if (size == 1)
+                return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
+            PyErr_Format(PyExc_TypeError,
+                "%.200s() takes exactly one argument (%zd given)",
+                f->m_ml->ml_name, size);
+            return NULL;
+        }
+        break;
+    default:
+        PyErr_SetString(PyExc_SystemError, "Bad call flags in "
+                        "__Pyx_CyFunction_Call. METH_OLDARGS is no "
+                        "longer supported!");
+        return NULL;
+    }
+    PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
+                 f->m_ml->ml_name);
+    return NULL;
+}
+#else
+static PyObject * __Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) {
+	return PyCFunction_Call(func, arg, kw);
+}
+#endif
+static PyTypeObject __pyx_CyFunctionType_type = {
+    PyVarObject_HEAD_INIT(0, 0)
+    "cython_function_or_method",
+    sizeof(__pyx_CyFunctionObject),
+    0,
+    (destructor) __Pyx_CyFunction_dealloc,
+    0,
+    0,
+    0,
+#if PY_MAJOR_VERSION < 3
+    0,
+#else
+    0,
+#endif
+    (reprfunc) __Pyx_CyFunction_repr,
+    0,
+    0,
+    0,
+    0,
+    __Pyx_CyFunction_Call,
+    0,
+    0,
+    0,
+    0,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+    0,
+    (traverseproc) __Pyx_CyFunction_traverse,
+    (inquiry) __Pyx_CyFunction_clear,
+    0,
+#if PY_VERSION_HEX < 0x030500A0
+    offsetof(__pyx_CyFunctionObject, func_weakreflist),
+#else
+    offsetof(PyCFunctionObject, m_weakreflist),
+#endif
+    0,
+    0,
+    __pyx_CyFunction_methods,
+    __pyx_CyFunction_members,
+    __pyx_CyFunction_getsets,
+    0,
+    0,
+    __Pyx_CyFunction_descr_get,
+    0,
+    offsetof(__pyx_CyFunctionObject, func_dict),
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+#if PY_VERSION_HEX >= 0x030400a1
+    0,
+#endif
+};
+static int __Pyx_CyFunction_init(void) {
+#if !CYTHON_COMPILING_IN_PYPY
+    __pyx_CyFunctionType_type.tp_call = PyCFunction_Call;
+#endif
+    __pyx_CyFunctionType = __Pyx_FetchCommonType(&__pyx_CyFunctionType_type);
+    if (__pyx_CyFunctionType == NULL) {
+        return -1;
+    }
+    return 0;
+}
+static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *func, size_t size, int pyobjects) {
+    __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
+    m->defaults = PyMem_Malloc(size);
+    if (!m->defaults)
+        return PyErr_NoMemory();
+    memset(m->defaults, 0, size);
+    m->defaults_pyobjects = pyobjects;
+    return m->defaults;
+}
+static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *func, PyObject *tuple) {
+    __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
+    m->defaults_tuple = tuple;
+    Py_INCREF(tuple);
+}
+static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *func, PyObject *dict) {
+    __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
+    m->defaults_kwdict = dict;
+    Py_INCREF(dict);
+}
+static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *func, PyObject *dict) {
+    __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
+    m->func_annotations = dict;
+    Py_INCREF(dict);
+}
+
+static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) {
+    PyObject* value = __Pyx_PyObject_GetAttrStr(module, name);
+    if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+        PyErr_Format(PyExc_ImportError,
+        #if PY_MAJOR_VERSION < 3
+            "cannot import name %.230s", PyString_AS_STRING(name));
+        #else
+            "cannot import name %S", name);
+        #endif
+    }
+    return value;
+}
+
+static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
+    int start = 0, mid = 0, end = count - 1;
+    if (end >= 0 && code_line > entries[end].code_line) {
+        return count;
+    }
+    while (start < end) {
+        mid = (start + end) / 2;
+        if (code_line < entries[mid].code_line) {
+            end = mid;
+        } else if (code_line > entries[mid].code_line) {
+             start = mid + 1;
+        } else {
+            return mid;
+        }
+    }
+    if (code_line <= entries[mid].code_line) {
+        return mid;
+    } else {
+        return mid + 1;
+    }
+}
+static PyCodeObject *__pyx_find_code_object(int code_line) {
+    PyCodeObject* code_object;
+    int pos;
+    if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) {
+        return NULL;
+    }
+    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
+    if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) {
+        return NULL;
+    }
+    code_object = __pyx_code_cache.entries[pos].code_object;
+    Py_INCREF(code_object);
+    return code_object;
+}
+static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) {
+    int pos, i;
+    __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries;
+    if (unlikely(!code_line)) {
+        return;
+    }
+    if (unlikely(!entries)) {
+        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry));
+        if (likely(entries)) {
+            __pyx_code_cache.entries = entries;
+            __pyx_code_cache.max_count = 64;
+            __pyx_code_cache.count = 1;
+            entries[0].code_line = code_line;
+            entries[0].code_object = code_object;
+            Py_INCREF(code_object);
+        }
+        return;
+    }
+    pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line);
+    if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) {
+        PyCodeObject* tmp = entries[pos].code_object;
+        entries[pos].code_object = code_object;
+        Py_DECREF(tmp);
+        return;
+    }
+    if (__pyx_code_cache.count == __pyx_code_cache.max_count) {
+        int new_max = __pyx_code_cache.max_count + 64;
+        entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc(
+            __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry));
+        if (unlikely(!entries)) {
+            return;
+        }
+        __pyx_code_cache.entries = entries;
+        __pyx_code_cache.max_count = new_max;
+    }
+    for (i=__pyx_code_cache.count; i>pos; i--) {
+        entries[i] = entries[i-1];
+    }
+    entries[pos].code_line = code_line;
+    entries[pos].code_object = code_object;
+    __pyx_code_cache.count++;
+    Py_INCREF(code_object);
+}
+
+#include "compile.h"
+#include "frameobject.h"
+#include "traceback.h"
+static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
+            const char *funcname, int c_line,
+            int py_line, const char *filename) {
+    PyCodeObject *py_code = 0;
+    PyObject *py_srcfile = 0;
+    PyObject *py_funcname = 0;
+    #if PY_MAJOR_VERSION < 3
+    py_srcfile = PyString_FromString(filename);
+    #else
+    py_srcfile = PyUnicode_FromString(filename);
+    #endif
+    if (!py_srcfile) goto bad;
+    if (c_line) {
+        #if PY_MAJOR_VERSION < 3
+        py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        #else
+        py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
+        #endif
+    }
+    else {
+        #if PY_MAJOR_VERSION < 3
+        py_funcname = PyString_FromString(funcname);
+        #else
+        py_funcname = PyUnicode_FromString(funcname);
+        #endif
+    }
+    if (!py_funcname) goto bad;
+    py_code = __Pyx_PyCode_New(
+        0,
+        0,
+        0,
+        0,
+        0,
+        __pyx_empty_bytes, /*PyObject *code,*/
+        __pyx_empty_tuple, /*PyObject *consts,*/
+        __pyx_empty_tuple, /*PyObject *names,*/
+        __pyx_empty_tuple, /*PyObject *varnames,*/
+        __pyx_empty_tuple, /*PyObject *freevars,*/
+        __pyx_empty_tuple, /*PyObject *cellvars,*/
+        py_srcfile,   /*PyObject *filename,*/
+        py_funcname,  /*PyObject *name,*/
+        py_line,
+        __pyx_empty_bytes  /*PyObject *lnotab*/
+    );
+    Py_DECREF(py_srcfile);
+    Py_DECREF(py_funcname);
+    return py_code;
+bad:
+    Py_XDECREF(py_srcfile);
+    Py_XDECREF(py_funcname);
+    return NULL;
+}
+static void __Pyx_AddTraceback(const char *funcname, int c_line,
+                               int py_line, const char *filename) {
+    PyCodeObject *py_code = 0;
+    PyFrameObject *py_frame = 0;
+    py_code = __pyx_find_code_object(c_line ? c_line : py_line);
+    if (!py_code) {
+        py_code = __Pyx_CreateCodeObjectForTraceback(
+            funcname, c_line, py_line, filename);
+        if (!py_code) goto bad;
+        __pyx_insert_code_object(c_line ? c_line : py_line, py_code);
+    }
+    py_frame = PyFrame_New(
+        PyThreadState_GET(), /*PyThreadState *tstate,*/
+        py_code,             /*PyCodeObject *code,*/
+        __pyx_d,      /*PyObject *globals,*/
+        0                    /*PyObject *locals*/
+    );
+    if (!py_frame) goto bad;
+    py_frame->f_lineno = py_line;
+    PyTraceBack_Here(py_frame);
+bad:
+    Py_XDECREF(py_code);
+    Py_XDECREF(py_frame);
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) {
+    const int neg_one = (int) -1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (is_unsigned) {
+        if (sizeof(int) < sizeof(long)) {
+            return PyInt_FromLong((long) value);
+        } else if (sizeof(int) <= sizeof(unsigned long)) {
+            return PyLong_FromUnsignedLong((unsigned long) value);
+        } else if (sizeof(int) <= sizeof(unsigned long long)) {
+            return PyLong_FromUnsignedLongLong((unsigned long long) value);
+        }
+    } else {
+        if (sizeof(int) <= sizeof(long)) {
+            return PyInt_FromLong((long) value);
+        } else if (sizeof(int) <= sizeof(long long)) {
+            return PyLong_FromLongLong((long long) value);
+        }
+    }
+    {
+        int one = 1; int little = (int)*(unsigned char *)&one;
+        unsigned char *bytes = (unsigned char *)&value;
+        return _PyLong_FromByteArray(bytes, sizeof(int),
+                                     little, !is_unsigned);
+    }
+}
+
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
+    PyObject *empty_list = 0;
+    PyObject *module = 0;
+    PyObject *global_dict = 0;
+    PyObject *empty_dict = 0;
+    PyObject *list;
+    #if PY_VERSION_HEX < 0x03030000
+    PyObject *py_import;
+    py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s_import);
+    if (!py_import)
+        goto bad;
+    #endif
+    if (from_list)
+        list = from_list;
+    else {
+        empty_list = PyList_New(0);
+        if (!empty_list)
+            goto bad;
+        list = empty_list;
+    }
+    global_dict = PyModule_GetDict(__pyx_m);
+    if (!global_dict)
+        goto bad;
+    empty_dict = PyDict_New();
+    if (!empty_dict)
+        goto bad;
+    {
+        #if PY_MAJOR_VERSION >= 3
+        if (level == -1) {
+            if (strchr(__Pyx_MODULE_NAME, '.')) {
+                #if PY_VERSION_HEX < 0x03030000
+                PyObject *py_level = PyInt_FromLong(1);
+                if (!py_level)
+                    goto bad;
+                module = PyObject_CallFunctionObjArgs(py_import,
+                    name, global_dict, empty_dict, list, py_level, NULL);
+                Py_DECREF(py_level);
+                #else
+                module = PyImport_ImportModuleLevelObject(
+                    name, global_dict, empty_dict, list, 1);
+                #endif
+                if (!module) {
+                    if (!PyErr_ExceptionMatches(PyExc_ImportError))
+                        goto bad;
+                    PyErr_Clear();
+                }
+            }
+            level = 0;
+        }
+        #endif
+        if (!module) {
+            #if PY_VERSION_HEX < 0x03030000
+            PyObject *py_level = PyInt_FromLong(level);
+            if (!py_level)
+                goto bad;
+            module = PyObject_CallFunctionObjArgs(py_import,
+                name, global_dict, empty_dict, list, py_level, NULL);
+            Py_DECREF(py_level);
+            #else
+            module = PyImport_ImportModuleLevelObject(
+                name, global_dict, empty_dict, list, level);
+            #endif
+        }
+    }
+bad:
+    #if PY_VERSION_HEX < 0x03030000
+    Py_XDECREF(py_import);
+    #endif
+    Py_XDECREF(empty_list);
+    Py_XDECREF(empty_dict);
+    return module;
+}
+
+#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)       \
+    {                                                                     \
+        func_type value = func_value;                                     \
+        if (sizeof(target_type) < sizeof(func_type)) {                    \
+            if (unlikely(value != (func_type) (target_type) value)) {     \
+                func_type zero = 0;                                       \
+                if (is_unsigned && unlikely(value < zero))                \
+                    goto raise_neg_overflow;                              \
+                else                                                      \
+                    goto raise_overflow;                                  \
+            }                                                             \
+        }                                                                 \
+        return (target_type) value;                                       \
+    }
+
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+  #include "longintrepr.h"
+ #endif
+#endif
+
+static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) {
+    const int neg_one = (int) -1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_MAJOR_VERSION < 3
+    if (likely(PyInt_Check(x))) {
+        if (sizeof(int) < sizeof(long)) {
+            __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x))
+        } else {
+            long val = PyInt_AS_LONG(x);
+            if (is_unsigned && unlikely(val < 0)) {
+                goto raise_neg_overflow;
+            }
+            return (int) val;
+        }
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+            switch (Py_SIZE(x)) {
+                case  0: return 0;
+                case  1: __PYX_VERIFY_RETURN_INT(int, digit, ((PyLongObject*)x)->ob_digit[0]);
+            }
+ #endif
+#endif
+            if (unlikely(Py_SIZE(x) < 0)) {
+                goto raise_neg_overflow;
+            }
+            if (sizeof(int) <= sizeof(unsigned long)) {
+                __PYX_VERIFY_RETURN_INT(int, unsigned long, PyLong_AsUnsignedLong(x))
+            } else if (sizeof(int) <= sizeof(unsigned long long)) {
+                __PYX_VERIFY_RETURN_INT(int, unsigned long long, PyLong_AsUnsignedLongLong(x))
+            }
+        } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+            switch (Py_SIZE(x)) {
+                case  0: return 0;
+                case  1: __PYX_VERIFY_RETURN_INT(int,  digit, +(((PyLongObject*)x)->ob_digit[0]));
+                case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, -(sdigit) ((PyLongObject*)x)->ob_digit[0]);
+            }
+ #endif
+#endif
+            if (sizeof(int) <= sizeof(long)) {
+                __PYX_VERIFY_RETURN_INT(int, long, PyLong_AsLong(x))
+            } else if (sizeof(int) <= sizeof(long long)) {
+                __PYX_VERIFY_RETURN_INT(int, long long, PyLong_AsLongLong(x))
+            }
+        }
+        {
+#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
+            PyErr_SetString(PyExc_RuntimeError,
+                            "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
+#else
+            int val;
+            PyObject *v = __Pyx_PyNumber_Int(x);
+ #if PY_MAJOR_VERSION < 3
+            if (likely(v) && !PyLong_Check(v)) {
+                PyObject *tmp = v;
+                v = PyNumber_Long(tmp);
+                Py_DECREF(tmp);
+            }
+ #endif
+            if (likely(v)) {
+                int one = 1; int is_little = (int)*(unsigned char *)&one;
+                unsigned char *bytes = (unsigned char *)&val;
+                int ret = _PyLong_AsByteArray((PyLongObject *)v,
+                                              bytes, sizeof(val),
+                                              is_little, !is_unsigned);
+                Py_DECREF(v);
+                if (likely(!ret))
+                    return val;
+            }
+#endif
+            return (int) -1;
+        }
+    } else {
+        int val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (int) -1;
+        val = __Pyx_PyInt_As_int(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+raise_overflow:
+    PyErr_SetString(PyExc_OverflowError,
+        "value too large to convert to int");
+    return (int) -1;
+raise_neg_overflow:
+    PyErr_SetString(PyExc_OverflowError,
+        "can't convert negative value to int");
+    return (int) -1;
+}
+
+static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) {
+    const long neg_one = (long) -1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+#if PY_MAJOR_VERSION < 3
+    if (likely(PyInt_Check(x))) {
+        if (sizeof(long) < sizeof(long)) {
+            __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x))
+        } else {
+            long val = PyInt_AS_LONG(x);
+            if (is_unsigned && unlikely(val < 0)) {
+                goto raise_neg_overflow;
+            }
+            return (long) val;
+        }
+    } else
+#endif
+    if (likely(PyLong_Check(x))) {
+        if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+            switch (Py_SIZE(x)) {
+                case  0: return 0;
+                case  1: __PYX_VERIFY_RETURN_INT(long, digit, ((PyLongObject*)x)->ob_digit[0]);
+            }
+ #endif
+#endif
+            if (unlikely(Py_SIZE(x) < 0)) {
+                goto raise_neg_overflow;
+            }
+            if (sizeof(long) <= sizeof(unsigned long)) {
+                __PYX_VERIFY_RETURN_INT(long, unsigned long, PyLong_AsUnsignedLong(x))
+            } else if (sizeof(long) <= sizeof(unsigned long long)) {
+                __PYX_VERIFY_RETURN_INT(long, unsigned long long, PyLong_AsUnsignedLongLong(x))
+            }
+        } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+ #if CYTHON_USE_PYLONG_INTERNALS
+            switch (Py_SIZE(x)) {
+                case  0: return 0;
+                case  1: __PYX_VERIFY_RETURN_INT(long,  digit, +(((PyLongObject*)x)->ob_digit[0]));
+                case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, -(sdigit) ((PyLongObject*)x)->ob_digit[0]);
+            }
+ #endif
+#endif
+            if (sizeof(long) <= sizeof(long)) {
+                __PYX_VERIFY_RETURN_INT(long, long, PyLong_AsLong(x))
+            } else if (sizeof(long) <= sizeof(long long)) {
+                __PYX_VERIFY_RETURN_INT(long, long long, PyLong_AsLongLong(x))
+            }
+        }
+        {
+#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
+            PyErr_SetString(PyExc_RuntimeError,
+                            "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
+#else
+            long val;
+            PyObject *v = __Pyx_PyNumber_Int(x);
+ #if PY_MAJOR_VERSION < 3
+            if (likely(v) && !PyLong_Check(v)) {
+                PyObject *tmp = v;
+                v = PyNumber_Long(tmp);
+                Py_DECREF(tmp);
+            }
+ #endif
+            if (likely(v)) {
+                int one = 1; int is_little = (int)*(unsigned char *)&one;
+                unsigned char *bytes = (unsigned char *)&val;
+                int ret = _PyLong_AsByteArray((PyLongObject *)v,
+                                              bytes, sizeof(val),
+                                              is_little, !is_unsigned);
+                Py_DECREF(v);
+                if (likely(!ret))
+                    return val;
+            }
+#endif
+            return (long) -1;
+        }
+    } else {
+        long val;
+        PyObject *tmp = __Pyx_PyNumber_Int(x);
+        if (!tmp) return (long) -1;
+        val = __Pyx_PyInt_As_long(tmp);
+        Py_DECREF(tmp);
+        return val;
+    }
+raise_overflow:
+    PyErr_SetString(PyExc_OverflowError,
+        "value too large to convert to long");
+    return (long) -1;
+raise_neg_overflow:
+    PyErr_SetString(PyExc_OverflowError,
+        "can't convert negative value to long");
+    return (long) -1;
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) {
+    const long neg_one = (long) -1, const_zero = 0;
+    const int is_unsigned = neg_one > const_zero;
+    if (is_unsigned) {
+        if (sizeof(long) < sizeof(long)) {
+            return PyInt_FromLong((long) value);
+        } else if (sizeof(long) <= sizeof(unsigned long)) {
+            return PyLong_FromUnsignedLong((unsigned long) value);
+        } else if (sizeof(long) <= sizeof(unsigned long long)) {
+            return PyLong_FromUnsignedLongLong((unsigned long long) value);
+        }
+    } else {
+        if (sizeof(long) <= sizeof(long)) {
+            return PyInt_FromLong((long) value);
+        } else if (sizeof(long) <= sizeof(long long)) {
+            return PyLong_FromLongLong((long long) value);
+        }
+    }
+    {
+        int one = 1; int little = (int)*(unsigned char *)&one;
+        unsigned char *bytes = (unsigned char *)&value;
+        return _PyLong_FromByteArray(bytes, sizeof(long),
+                                     little, !is_unsigned);
+    }
+}
+
+static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) {
+    PyObject *method, *result = NULL;
+    method = __Pyx_PyObject_GetAttrStr(obj, method_name);
+    if (unlikely(!method)) goto bad;
+#if CYTHON_COMPILING_IN_CPYTHON
+    if (likely(PyMethod_Check(method))) {
+        PyObject *self = PyMethod_GET_SELF(method);
+        if (likely(self)) {
+            PyObject *args;
+            PyObject *function = PyMethod_GET_FUNCTION(method);
+            args = PyTuple_New(2);
+            if (unlikely(!args)) goto bad;
+            Py_INCREF(self);
+            PyTuple_SET_ITEM(args, 0, self);
+            Py_INCREF(arg);
+            PyTuple_SET_ITEM(args, 1, arg);
+            Py_INCREF(function);
+            Py_DECREF(method); method = NULL;
+            result = __Pyx_PyObject_Call(function, args, NULL);
+            Py_DECREF(args);
+            Py_DECREF(function);
+            return result;
+        }
+    }
+#endif
+    result = __Pyx_PyObject_CallOneArg(method, arg);
+bad:
+    Py_XDECREF(method);
+    return result;
+}
+
+static PyObject *__Pyx_Generator_Next(PyObject *self);
+static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value);
+static PyObject *__Pyx_Generator_Close(PyObject *self);
+static PyObject *__Pyx_Generator_Throw(PyObject *gen, PyObject *args);
+static PyTypeObject *__pyx_GeneratorType = 0;
+#define __Pyx_Generator_CheckExact(obj) (Py_TYPE(obj) == __pyx_GeneratorType)
+#define __Pyx_Generator_Undelegate(gen) Py_CLEAR((gen)->yieldfrom)
+#if 1 || PY_VERSION_HEX < 0x030300B0
+static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
+    PyObject *et, *ev, *tb;
+    PyObject *value = NULL;
+    __Pyx_ErrFetch(&et, &ev, &tb);
+    if (!et) {
+        Py_XDECREF(tb);
+        Py_XDECREF(ev);
+        Py_INCREF(Py_None);
+        *pvalue = Py_None;
+        return 0;
+    }
+    if (unlikely(et != PyExc_StopIteration) &&
+            unlikely(!PyErr_GivenExceptionMatches(et, PyExc_StopIteration))) {
+        __Pyx_ErrRestore(et, ev, tb);
+        return -1;
+    }
+    if (likely(et == PyExc_StopIteration)) {
+        if (likely(!ev) || !PyObject_IsInstance(ev, PyExc_StopIteration)) {
+            if (!ev) {
+                Py_INCREF(Py_None);
+                ev = Py_None;
+            }
+            Py_XDECREF(tb);
+            Py_DECREF(et);
+            *pvalue = ev;
+            return 0;
+        }
+    }
+    PyErr_NormalizeException(&et, &ev, &tb);
+    if (unlikely(!PyObject_IsInstance(ev, PyExc_StopIteration))) {
+        __Pyx_ErrRestore(et, ev, tb);
+        return -1;
+    }
+    Py_XDECREF(tb);
+    Py_DECREF(et);
+#if PY_VERSION_HEX >= 0x030300A0
+    value = ((PyStopIterationObject *)ev)->value;
+    Py_INCREF(value);
+    Py_DECREF(ev);
+#else
+    {
+        PyObject* args = PyObject_GetAttr(ev, __pyx_n_s_args);
+        Py_DECREF(ev);
+        if (likely(args)) {
+            value = PyObject_GetItem(args, 0);
+            Py_DECREF(args);
+        }
+        if (unlikely(!value)) {
+            __Pyx_ErrRestore(NULL, NULL, NULL);
+            Py_INCREF(Py_None);
+            value = Py_None;
+        }
+    }
+#endif
+    *pvalue = value;
+    return 0;
+}
+#endif
+static CYTHON_INLINE
+void __Pyx_Generator_ExceptionClear(__pyx_GeneratorObject *self) {
+    PyObject *exc_type = self->exc_type;
+    PyObject *exc_value = self->exc_value;
+    PyObject *exc_traceback = self->exc_traceback;
+    self->exc_type = NULL;
+    self->exc_value = NULL;
+    self->exc_traceback = NULL;
+    Py_XDECREF(exc_type);
+    Py_XDECREF(exc_value);
+    Py_XDECREF(exc_traceback);
+}
+static CYTHON_INLINE
+int __Pyx_Generator_CheckRunning(__pyx_GeneratorObject *gen) {
+    if (unlikely(gen->is_running)) {
+        PyErr_SetString(PyExc_ValueError,
+                        "generator already executing");
+        return 1;
+    }
+    return 0;
+}
+static CYTHON_INLINE
+PyObject *__Pyx_Generator_SendEx(__pyx_GeneratorObject *self, PyObject *value) {
+    PyObject *retval;
+    assert(!self->is_running);
+    if (unlikely(self->resume_label == 0)) {
+        if (unlikely(value && value != Py_None)) {
+            PyErr_SetString(PyExc_TypeError,
+                            "can't send non-None value to a "
+                            "just-started generator");
+            return NULL;
+        }
+    }
+    if (unlikely(self->resume_label == -1)) {
+        PyErr_SetNone(PyExc_StopIteration);
+        return NULL;
+    }
+    if (value) {
+#if CYTHON_COMPILING_IN_PYPY
+#else
+        if (self->exc_traceback) {
+            PyThreadState *tstate = PyThreadState_GET();
+            PyTracebackObject *tb = (PyTracebackObject *) self->exc_traceback;
+            PyFrameObject *f = tb->tb_frame;
+            Py_XINCREF(tstate->frame);
+            assert(f->f_back == NULL);
+            f->f_back = tstate->frame;
+        }
+#endif
+        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value,
+                            &self->exc_traceback);
+    } else {
+        __Pyx_Generator_ExceptionClear(self);
+    }
+    self->is_running = 1;
+    retval = self->body((PyObject *) self, value);
+    self->is_running = 0;
+    if (retval) {
+        __Pyx_ExceptionSwap(&self->exc_type, &self->exc_value,
+                            &self->exc_traceback);
+#if CYTHON_COMPILING_IN_PYPY
+#else
+        if (self->exc_traceback) {
+            PyTracebackObject *tb = (PyTracebackObject *) self->exc_traceback;
+            PyFrameObject *f = tb->tb_frame;
+            Py_CLEAR(f->f_back);
+        }
+#endif
+    } else {
+        __Pyx_Generator_ExceptionClear(self);
+    }
+    return retval;
+}
+static CYTHON_INLINE
+PyObject *__Pyx_Generator_FinishDelegation(__pyx_GeneratorObject *gen) {
+    PyObject *ret;
+    PyObject *val = NULL;
+    __Pyx_Generator_Undelegate(gen);
+    __Pyx_PyGen_FetchStopIterationValue(&val);
+    ret = __Pyx_Generator_SendEx(gen, val);
+    Py_XDECREF(val);
+    return ret;
+}
+static PyObject *__Pyx_Generator_Next(PyObject *self) {
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject*) self;
+    PyObject *yf = gen->yieldfrom;
+    if (unlikely(__Pyx_Generator_CheckRunning(gen)))
+        return NULL;
+    if (yf) {
+        PyObject *ret;
+        gen->is_running = 1;
+        ret = Py_TYPE(yf)->tp_iternext(yf);
+        gen->is_running = 0;
+        if (likely(ret)) {
+            return ret;
+        }
+        return __Pyx_Generator_FinishDelegation(gen);
+    }
+    return __Pyx_Generator_SendEx(gen, Py_None);
+}
+static PyObject *__Pyx_Generator_Send(PyObject *self, PyObject *value) {
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject*) self;
+    PyObject *yf = gen->yieldfrom;
+    if (unlikely(__Pyx_Generator_CheckRunning(gen)))
+        return NULL;
+    if (yf) {
+        PyObject *ret;
+        gen->is_running = 1;
+        if (__Pyx_Generator_CheckExact(yf)) {
+            ret = __Pyx_Generator_Send(yf, value);
+        } else {
+            if (value == Py_None)
+                ret = PyIter_Next(yf);
+            else
+                ret = __Pyx_PyObject_CallMethod1(yf, __pyx_n_s_send, value);
+        }
+        gen->is_running = 0;
+        if (likely(ret)) {
+            return ret;
+        }
+        return __Pyx_Generator_FinishDelegation(gen);
+    }
+    return __Pyx_Generator_SendEx(gen, value);
+}
+static int __Pyx_Generator_CloseIter(__pyx_GeneratorObject *gen, PyObject *yf) {
+    PyObject *retval = NULL;
+    int err = 0;
+    if (__Pyx_Generator_CheckExact(yf)) {
+        retval = __Pyx_Generator_Close(yf);
+        if (!retval)
+            return -1;
+    } else {
+        PyObject *meth;
+        gen->is_running = 1;
+        meth = PyObject_GetAttr(yf, __pyx_n_s_close);
+        if (unlikely(!meth)) {
+            if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+                PyErr_WriteUnraisable(yf);
+            }
+            PyErr_Clear();
+        } else {
+            retval = PyObject_CallFunction(meth, NULL);
+            Py_DECREF(meth);
+            if (!retval)
+                err = -1;
+        }
+        gen->is_running = 0;
+    }
+    Py_XDECREF(retval);
+    return err;
+}
+static PyObject *__Pyx_Generator_Close(PyObject *self) {
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
+    PyObject *retval, *raised_exception;
+    PyObject *yf = gen->yieldfrom;
+    int err = 0;
+    if (unlikely(__Pyx_Generator_CheckRunning(gen)))
+        return NULL;
+    if (yf) {
+        Py_INCREF(yf);
+        err = __Pyx_Generator_CloseIter(gen, yf);
+        __Pyx_Generator_Undelegate(gen);
+        Py_DECREF(yf);
+    }
+    if (err == 0)
+        PyErr_SetNone(PyExc_GeneratorExit);
+    retval = __Pyx_Generator_SendEx(gen, NULL);
+    if (retval) {
+        Py_DECREF(retval);
+        PyErr_SetString(PyExc_RuntimeError,
+                        "generator ignored GeneratorExit");
+        return NULL;
+    }
+    raised_exception = PyErr_Occurred();
+    if (!raised_exception
+        || raised_exception == PyExc_StopIteration
+        || raised_exception == PyExc_GeneratorExit
+        || PyErr_GivenExceptionMatches(raised_exception, PyExc_GeneratorExit)
+        || PyErr_GivenExceptionMatches(raised_exception, PyExc_StopIteration))
+    {
+        if (raised_exception) PyErr_Clear();
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+    return NULL;
+}
+static PyObject *__Pyx_Generator_Throw(PyObject *self, PyObject *args) {
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
+    PyObject *typ;
+    PyObject *tb = NULL;
+    PyObject *val = NULL;
+    PyObject *yf = gen->yieldfrom;
+    if (!PyArg_UnpackTuple(args, (char *)"throw", 1, 3, &typ, &val, &tb))
+        return NULL;
+    if (unlikely(__Pyx_Generator_CheckRunning(gen)))
+        return NULL;
+    if (yf) {
+        PyObject *ret;
+        Py_INCREF(yf);
+        if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) {
+            int err = __Pyx_Generator_CloseIter(gen, yf);
+            Py_DECREF(yf);
+            __Pyx_Generator_Undelegate(gen);
+            if (err < 0)
+                return __Pyx_Generator_SendEx(gen, NULL);
+            goto throw_here;
+        }
+        gen->is_running = 1;
+        if (__Pyx_Generator_CheckExact(yf)) {
+            ret = __Pyx_Generator_Throw(yf, args);
+        } else {
+            PyObject *meth = PyObject_GetAttr(yf, __pyx_n_s_throw);
+            if (unlikely(!meth)) {
+                Py_DECREF(yf);
+                if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+                    gen->is_running = 0;
+                    return NULL;
+                }
+                PyErr_Clear();
+                __Pyx_Generator_Undelegate(gen);
+                gen->is_running = 0;
+                goto throw_here;
+            }
+            ret = PyObject_CallObject(meth, args);
+            Py_DECREF(meth);
+        }
+        gen->is_running = 0;
+        Py_DECREF(yf);
+        if (!ret) {
+            ret = __Pyx_Generator_FinishDelegation(gen);
+        }
+        return ret;
+    }
+throw_here:
+    __Pyx_Raise(typ, val, tb, NULL);
+    return __Pyx_Generator_SendEx(gen, NULL);
+}
+static int __Pyx_Generator_traverse(PyObject *self, visitproc visit, void *arg) {
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
+    Py_VISIT(gen->closure);
+    Py_VISIT(gen->classobj);
+    Py_VISIT(gen->yieldfrom);
+    Py_VISIT(gen->exc_type);
+    Py_VISIT(gen->exc_value);
+    Py_VISIT(gen->exc_traceback);
+    return 0;
+}
+static int __Pyx_Generator_clear(PyObject *self) {
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
+    Py_CLEAR(gen->closure);
+    Py_CLEAR(gen->classobj);
+    Py_CLEAR(gen->yieldfrom);
+    Py_CLEAR(gen->exc_type);
+    Py_CLEAR(gen->exc_value);
+    Py_CLEAR(gen->exc_traceback);
+    Py_CLEAR(gen->gi_name);
+    Py_CLEAR(gen->gi_qualname);
+    return 0;
+}
+static void __Pyx_Generator_dealloc(PyObject *self) {
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
+    PyObject_GC_UnTrack(gen);
+    if (gen->gi_weakreflist != NULL)
+        PyObject_ClearWeakRefs(self);
+    if (gen->resume_label > 0) {
+        PyObject_GC_Track(self);
+#if PY_VERSION_HEX >= 0x030400a1
+        if (PyObject_CallFinalizerFromDealloc(self))
+#else
+        Py_TYPE(gen)->tp_del(self);
+        if (self->ob_refcnt > 0)
+#endif
+        {
+            return;
+        }
+        PyObject_GC_UnTrack(self);
+    }
+    __Pyx_Generator_clear(self);
+    PyObject_GC_Del(gen);
+}
+static void __Pyx_Generator_del(PyObject *self) {
+    PyObject *res;
+    PyObject *error_type, *error_value, *error_traceback;
+    __pyx_GeneratorObject *gen = (__pyx_GeneratorObject *) self;
+    if (gen->resume_label <= 0)
+        return ;
+#if PY_VERSION_HEX < 0x030400a1
+    assert(self->ob_refcnt == 0);
+    self->ob_refcnt = 1;
+#endif
+    __Pyx_ErrFetch(&error_type, &error_value, &error_traceback);
+    res = __Pyx_Generator_Close(self);
+    if (res == NULL)
+        PyErr_WriteUnraisable(self);
+    else
+        Py_DECREF(res);
+    __Pyx_ErrRestore(error_type, error_value, error_traceback);
+#if PY_VERSION_HEX < 0x030400a1
+    assert(self->ob_refcnt > 0);
+    if (--self->ob_refcnt == 0) {
+        return;
+    }
+    {
+        Py_ssize_t refcnt = self->ob_refcnt;
+        _Py_NewReference(self);
+        self->ob_refcnt = refcnt;
+    }
+#if CYTHON_COMPILING_IN_CPYTHON
+    assert(PyType_IS_GC(self->ob_type) &&
+           _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
+    _Py_DEC_REFTOTAL;
+#endif
+#ifdef COUNT_ALLOCS
+    --Py_TYPE(self)->tp_frees;
+    --Py_TYPE(self)->tp_allocs;
+#endif
+#endif
+}
+static PyObject *
+__Pyx_Generator_get_name(__pyx_GeneratorObject *self)
+{
+    Py_INCREF(self->gi_name);
+    return self->gi_name;
+}
+static int
+__Pyx_Generator_set_name(__pyx_GeneratorObject *self, PyObject *value)
+{
+    PyObject *tmp;
+#if PY_MAJOR_VERSION >= 3
+    if (unlikely(value == NULL || !PyUnicode_Check(value))) {
+#else
+    if (unlikely(value == NULL || !PyString_Check(value))) {
+#endif
+        PyErr_SetString(PyExc_TypeError,
+                        "__name__ must be set to a string object");
+        return -1;
+    }
+    tmp = self->gi_name;
+    Py_INCREF(value);
+    self->gi_name = value;
+    Py_XDECREF(tmp);
+    return 0;
+}
+static PyObject *
+__Pyx_Generator_get_qualname(__pyx_GeneratorObject *self)
+{
+    Py_INCREF(self->gi_qualname);
+    return self->gi_qualname;
+}
+static int
+__Pyx_Generator_set_qualname(__pyx_GeneratorObject *self, PyObject *value)
+{
+    PyObject *tmp;
+#if PY_MAJOR_VERSION >= 3
+    if (unlikely(value == NULL || !PyUnicode_Check(value))) {
+#else
+    if (unlikely(value == NULL || !PyString_Check(value))) {
+#endif
+        PyErr_SetString(PyExc_TypeError,
+                        "__qualname__ must be set to a string object");
+        return -1;
+    }
+    tmp = self->gi_qualname;
+    Py_INCREF(value);
+    self->gi_qualname = value;
+    Py_XDECREF(tmp);
+    return 0;
+}
+static PyGetSetDef __pyx_Generator_getsets[] = {
+    {(char *) "__name__", (getter)__Pyx_Generator_get_name, (setter)__Pyx_Generator_set_name,
+     (char*) PyDoc_STR("name of the generator"), 0},
+    {(char *) "__qualname__", (getter)__Pyx_Generator_get_qualname, (setter)__Pyx_Generator_set_qualname,
+     (char*) PyDoc_STR("qualified name of the generator"), 0},
+    {0, 0, 0, 0, 0}
+};
+static PyMemberDef __pyx_Generator_memberlist[] = {
+    {(char *) "gi_running", T_BOOL, offsetof(__pyx_GeneratorObject, is_running), READONLY, NULL},
+    {0, 0, 0, 0, 0}
+};
+static PyMethodDef __pyx_Generator_methods[] = {
+    {"send", (PyCFunction) __Pyx_Generator_Send, METH_O, 0},
+    {"throw", (PyCFunction) __Pyx_Generator_Throw, METH_VARARGS, 0},
+    {"close", (PyCFunction) __Pyx_Generator_Close, METH_NOARGS, 0},
+    {0, 0, 0, 0}
+};
+static PyTypeObject __pyx_GeneratorType_type = {
+    PyVarObject_HEAD_INIT(0, 0)
+    "generator",
+    sizeof(__pyx_GeneratorObject),
+    0,
+    (destructor) __Pyx_Generator_dealloc,
+    0,
+    0,
+    0,
+#if PY_MAJOR_VERSION < 3
+    0,
+#else
+    0,
+#endif
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE,
+    0,
+    (traverseproc) __Pyx_Generator_traverse,
+    0,
+    0,
+    offsetof(__pyx_GeneratorObject, gi_weakreflist),
+    0,
+    (iternextfunc) __Pyx_Generator_Next,
+    __pyx_Generator_methods,
+    __pyx_Generator_memberlist,
+    __pyx_Generator_getsets,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+#if PY_VERSION_HEX >= 0x030400a1
+    0,
+#else
+    __Pyx_Generator_del,
+#endif
+    0,
+#if PY_VERSION_HEX >= 0x030400a1
+    __Pyx_Generator_del,
+#endif
+};
+static __pyx_GeneratorObject *__Pyx_Generator_New(__pyx_generator_body_t body,
+                                                  PyObject *closure, PyObject *name, PyObject *qualname) {
+    __pyx_GeneratorObject *gen =
+        PyObject_GC_New(__pyx_GeneratorObject, &__pyx_GeneratorType_type);
+    if (gen == NULL)
+        return NULL;
+    gen->body = body;
+    gen->closure = closure;
+    Py_XINCREF(closure);
+    gen->is_running = 0;
+    gen->resume_label = 0;
+    gen->classobj = NULL;
+    gen->yieldfrom = NULL;
+    gen->exc_type = NULL;
+    gen->exc_value = NULL;
+    gen->exc_traceback = NULL;
+    gen->gi_weakreflist = NULL;
+    Py_XINCREF(qualname);
+    gen->gi_qualname = qualname;
+    Py_XINCREF(name);
+    gen->gi_name = name;
+    PyObject_GC_Track(gen);
+    return gen;
+}
+static int __pyx_Generator_init(void) {
+    __pyx_GeneratorType_type.tp_getattro = PyObject_GenericGetAttr;
+    __pyx_GeneratorType_type.tp_iter = PyObject_SelfIter;
+    __pyx_GeneratorType = __Pyx_FetchCommonType(&__pyx_GeneratorType_type);
+    if (__pyx_GeneratorType == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int __Pyx_check_binary_version(void) {
+    char ctversion[4], rtversion[4];
+    PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION);
+    PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion());
+    if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) {
+        char message[200];
+        PyOS_snprintf(message, sizeof(message),
+                      "compiletime version %s of module '%.100s' "
+                      "does not match runtime version %s",
+                      ctversion, __Pyx_MODULE_NAME, rtversion);
+        return PyErr_WarnEx(NULL, message, 1);
+    }
+    return 0;
+}
+
+static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig) {
+    PyObject *d = 0;
+    PyObject *cobj = 0;
+    union {
+        void (*fp)(void);
+        void *p;
+    } tmp;
+    d = PyObject_GetAttrString(__pyx_m, (char *)"__pyx_capi__");
+    if (!d) {
+        PyErr_Clear();
+        d = PyDict_New();
+        if (!d)
+            goto bad;
+        Py_INCREF(d);
+        if (PyModule_AddObject(__pyx_m, (char *)"__pyx_capi__", d) < 0)
+            goto bad;
+    }
+    tmp.fp = f;
+#if PY_VERSION_HEX >= 0x02070000
+    cobj = PyCapsule_New(tmp.p, sig, 0);
+#else
+    cobj = PyCObject_FromVoidPtrAndDesc(tmp.p, (void *)sig, 0);
+#endif
+    if (!cobj)
+        goto bad;
+    if (PyDict_SetItemString(d, name, cobj) < 0)
+        goto bad;
+    Py_DECREF(cobj);
+    Py_DECREF(d);
+    return 0;
+bad:
+    Py_XDECREF(cobj);
+    Py_XDECREF(d);
+    return -1;
+}
+
+#ifndef __PYX_HAVE_RT_ImportModule
+#define __PYX_HAVE_RT_ImportModule
+static PyObject *__Pyx_ImportModule(const char *name) {
+    PyObject *py_name = 0;
+    PyObject *py_module = 0;
+    py_name = __Pyx_PyIdentifier_FromString(name);
+    if (!py_name)
+        goto bad;
+    py_module = PyImport_Import(py_name);
+    Py_DECREF(py_name);
+    return py_module;
+bad:
+    Py_XDECREF(py_name);
+    return 0;
+}
+#endif
+
+#ifndef __PYX_HAVE_RT_ImportType
+#define __PYX_HAVE_RT_ImportType
+static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class_name,
+    size_t size, int strict)
+{
+    PyObject *py_module = 0;
+    PyObject *result = 0;
+    PyObject *py_name = 0;
+    char warning[200];
+    Py_ssize_t basicsize;
+#ifdef Py_LIMITED_API
+    PyObject *py_basicsize;
+#endif
+    py_module = __Pyx_ImportModule(module_name);
+    if (!py_module)
+        goto bad;
+    py_name = __Pyx_PyIdentifier_FromString(class_name);
+    if (!py_name)
+        goto bad;
+    result = PyObject_GetAttr(py_module, py_name);
+    Py_DECREF(py_name);
+    py_name = 0;
+    Py_DECREF(py_module);
+    py_module = 0;
+    if (!result)
+        goto bad;
+    if (!PyType_Check(result)) {
+        PyErr_Format(PyExc_TypeError,
+            "%.200s.%.200s is not a type object",
+            module_name, class_name);
+        goto bad;
+    }
+#ifndef Py_LIMITED_API
+    basicsize = ((PyTypeObject *)result)->tp_basicsize;
+#else
+    py_basicsize = PyObject_GetAttrString(result, "__basicsize__");
+    if (!py_basicsize)
+        goto bad;
+    basicsize = PyLong_AsSsize_t(py_basicsize);
+    Py_DECREF(py_basicsize);
+    py_basicsize = 0;
+    if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred())
+        goto bad;
+#endif
+    if (!strict && (size_t)basicsize > size) {
+        PyOS_snprintf(warning, sizeof(warning),
+            "%s.%s size changed, may indicate binary incompatibility",
+            module_name, class_name);
+        if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad;
+    }
+    else if ((size_t)basicsize != size) {
+        PyErr_Format(PyExc_ValueError,
+            "%.200s.%.200s has the wrong size, try recompiling",
+            module_name, class_name);
+        goto bad;
+    }
+    return (PyTypeObject *)result;
+bad:
+    Py_XDECREF(py_module);
+    Py_XDECREF(result);
+    return NULL;
+}
+#endif
+
+static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
+    while (t->p) {
+        #if PY_MAJOR_VERSION < 3
+        if (t->is_unicode) {
+            *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL);
+        } else if (t->intern) {
+            *t->p = PyString_InternFromString(t->s);
+        } else {
+            *t->p = PyString_FromStringAndSize(t->s, t->n - 1);
+        }
+        #else
+        if (t->is_unicode | t->is_str) {
+            if (t->intern) {
+                *t->p = PyUnicode_InternFromString(t->s);
+            } else if (t->encoding) {
+                *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL);
+            } else {
+                *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1);
+            }
+        } else {
+            *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1);
+        }
+        #endif
+        if (!*t->p)
+            return -1;
+        ++t;
+    }
+    return 0;
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) {
+    return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str));
+}
+static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) {
+    Py_ssize_t ignore;
+    return __Pyx_PyObject_AsStringAndSize(o, &ignore);
+}
+static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) {
+#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
+    if (
+#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+            __Pyx_sys_getdefaultencoding_not_ascii &&
+#endif
+            PyUnicode_Check(o)) {
+#if PY_VERSION_HEX < 0x03030000
+        char* defenc_c;
+        PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL);
+        if (!defenc) return NULL;
+        defenc_c = PyBytes_AS_STRING(defenc);
+#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+        {
+            char* end = defenc_c + PyBytes_GET_SIZE(defenc);
+            char* c;
+            for (c = defenc_c; c < end; c++) {
+                if ((unsigned char) (*c) >= 128) {
+                    PyUnicode_AsASCIIString(o);
+                    return NULL;
+                }
+            }
+        }
+#endif
+        *length = PyBytes_GET_SIZE(defenc);
+        return defenc_c;
+#else
+        if (__Pyx_PyUnicode_READY(o) == -1) return NULL;
+#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+        if (PyUnicode_IS_ASCII(o)) {
+            *length = PyUnicode_GET_LENGTH(o);
+            return PyUnicode_AsUTF8(o);
+        } else {
+            PyUnicode_AsASCIIString(o);
+            return NULL;
+        }
+#else
+        return PyUnicode_AsUTF8AndSize(o, length);
+#endif
+#endif
+    } else
+#endif
+#if !CYTHON_COMPILING_IN_PYPY
+    if (PyByteArray_Check(o)) {
+        *length = PyByteArray_GET_SIZE(o);
+        return PyByteArray_AS_STRING(o);
+    } else
+#endif
+    {
+        char* result;
+        int r = PyBytes_AsStringAndSize(o, &result, length);
+        if (unlikely(r < 0)) {
+            return NULL;
+        } else {
+            return result;
+        }
+    }
+}
+static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
+   int is_true = x == Py_True;
+   if (is_true | (x == Py_False) | (x == Py_None)) return is_true;
+   else return PyObject_IsTrue(x);
+}
+static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
+  PyNumberMethods *m;
+  const char *name = NULL;
+  PyObject *res = NULL;
+#if PY_MAJOR_VERSION < 3
+  if (PyInt_Check(x) || PyLong_Check(x))
+#else
+  if (PyLong_Check(x))
+#endif
+    return Py_INCREF(x), x;
+  m = Py_TYPE(x)->tp_as_number;
+#if PY_MAJOR_VERSION < 3
+  if (m && m->nb_int) {
+    name = "int";
+    res = PyNumber_Int(x);
+  }
+  else if (m && m->nb_long) {
+    name = "long";
+    res = PyNumber_Long(x);
+  }
+#else
+  if (m && m->nb_int) {
+    name = "int";
+    res = PyNumber_Long(x);
+  }
+#endif
+  if (res) {
+#if PY_MAJOR_VERSION < 3
+    if (!PyInt_Check(res) && !PyLong_Check(res)) {
+#else
+    if (!PyLong_Check(res)) {
+#endif
+      PyErr_Format(PyExc_TypeError,
+                   "__%.4s__ returned non-%.4s (type %.200s)",
+                   name, name, Py_TYPE(res)->tp_name);
+      Py_DECREF(res);
+      return NULL;
+    }
+  }
+  else if (!PyErr_Occurred()) {
+    PyErr_SetString(PyExc_TypeError,
+                    "an integer is required");
+  }
+  return res;
+}
+static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
+  Py_ssize_t ival;
+  PyObject *x;
+#if PY_MAJOR_VERSION < 3
+  if (likely(PyInt_CheckExact(b)))
+      return PyInt_AS_LONG(b);
+#endif
+  if (likely(PyLong_CheckExact(b))) {
+    #if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+     #if CYTHON_USE_PYLONG_INTERNALS
+       switch (Py_SIZE(b)) {
+       case -1: return -(sdigit)((PyLongObject*)b)->ob_digit[0];
+       case  0: return 0;
+       case  1: return ((PyLongObject*)b)->ob_digit[0];
+       }
+     #endif
+    #endif
+    return PyLong_AsSsize_t(b);
+  }
+  x = PyNumber_Index(b);
+  if (!x) return -1;
+  ival = PyInt_AsSsize_t(x);
+  Py_DECREF(x);
+  return ival;
+}
+static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
+    return PyInt_FromSize_t(ival);
+}
+
+
+#endif /* Py_PYTHON_H */
diff --git a/pymusic/pymusic.pxd b/pymusic/pymusic.pxd
new file mode 100644
index 0000000..dccdc76
--- /dev/null
+++ b/pymusic/pymusic.pxd
@@ -0,0 +1,234 @@
+cimport mpi4py.MPI as MPI
+from mpi4py.mpi_c cimport *
+
+from libcpp cimport bool as cbool
+from libcpp.string cimport string
+from cpython.ref cimport PyObject
+
+###########################################################
+
+cdef extern from "music/predict_rank.hh" namespace "MUSIC":
+    cdef int CPredictRank "MUSIC::predictRank" (int, char**)
+
+cdef extern from "music/message.hh" namespace "MUSIC":
+    cdef cppclass CMessageHandler "MUSIC::MessageHandler":
+        pass
+
+cdef extern from "music/music_c.h" namespace "MUSIC":
+    cdef cppclass CEventHandler "MUSIC::EventHandler":
+        pass
+    cdef cppclass CEHLocal "MUSIC::EHLocal"(CEventHandler):
+        CEHLocal(PyObject*)
+    cdef cppclass CEHGlobal "MUSIC::EHGlobal"(CEventHandler):
+        CEHGlobal(PyObject*)
+    cdef cppclass CMHandler "MUSIC::MHandler"(CMessageHandler):
+        CMHandler(PyObject*, cbool)
+
+cdef extern from "music/event.hh" namespace "MUSIC":
+    cdef cppclass CEventHandlerGlobalIndex "MUSIC::EventHandlerGlobalIndex":
+        pass
+    cdef cppclass CEventHandlerLocalIndex "MUSIC::EventHandlerLocalIndex":
+        pass
+    cdef cppclass CEventHandlerPtr "MUSIC::EventHandlerPtr":
+        pass
+
+cdef extern from "music/data_map.hh" namespace "MUSIC":
+    cdef cppclass CDataMap "MUSIC::DataMap":
+        pass
+
+cdef extern from "music/index_map.hh" namespace "MUSIC":
+    cdef cppclass CIndex "MUSIC::Index":
+        int WILDCARD_MAX
+    ctypedef enum IndexType "MUSIC::Index::Type":
+            IndexGLOBAL "MUSIC::Index::GLOBAL", 
+            IndexLOCAL "MUSIC::Index::LOCAL"
+
+    cdef cppclass GlobalIndex(CIndex):
+        GlobalIndex(int)
+
+    cdef cppclass LocalIndex(CIndex):
+        LocalIndex(int)
+
+    cdef cppclass CIndexMap "MUSIC::IndexMap":
+        pass
+
+cdef extern from "music/permutation_index.hh" namespace "MUSIC":
+    cdef cppclass PermutationIndex(CIndexMap):
+        PermutationIndex(GlobalIndex*, int)
+
+cdef extern from "music/linear_index.hh" namespace "MUSIC":
+    cdef cppclass LinearIndex(CIndexMap):
+        LinearIndex(GlobalIndex, int)
+
+cdef extern from "music/array_data.hh" namespace "MUSIC":
+    cdef cppclass CArrayData "MUSIC::ArrayData"(CDataMap):
+        CArrayData(void*, MPI_Datatype, int, int)
+        CArrayData(void*, MPI_Datatype, CIndexMap*)
+
+cdef extern from "music/port.hh" namespace "MUSIC":
+    cdef cppclass CPort "MUSIC::Port":
+        cbool isConnected()
+        cbool hasWidth()
+        int width()
+
+    cdef cppclass CContInputPort "MUSIC::ContInputPort"(CPort):
+        pass
+
+    cdef cppclass CContOutputPort "MUSIC::ContOutputPort"(CPort):
+        pass
+
+    cdef cppclass CEventInputPort "MUSIC::EventInputPort"(CPort):
+        pass
+
+    cdef cppclass CEventOutputPort "MUSIC::EventOutputPort"(CPort):
+        pass
+
+    cdef cppclass CMessageInputPort "MUSIC::MessageInputPort"(CPort):
+        pass
+
+    cdef cppclass CMessageOutputPort "MUSIC::MessageOutputPort"(CPort):
+        void insertMessage(double, void*, size_t)
+
+# This is necessary for the virtual downcast
+cdef extern from *:
+    CContInputPort*   dc_CContInputPort   \
+        "dynamic_cast<MUSIC::ContInputPort*>" (CPort*)
+    CContOutputPort*  dc_CContOutputPort  \
+        "dynamic_cast<MUSIC::ContOutputPort*>"(CPort*)
+    CEventInputPort*  dc_CEventInputPort  \
+        "dynamic_cast<MUSIC::EventInputPort*>" (CPort*)
+    CEventOutputPort* dc_CEventOutputPort \
+        "dynamic_cast<MUSIC::EventOutputPort*>"(CPort*)
+    CMessageInputPort*  dc_CMessageInputPort  \
+        "dynamic_cast<MUSIC::MessageInputPort*>" (CPort*)
+    CMessageOutputPort* dc_CMessageOutputPort \
+        "dynamic_cast<MUSIC::MessageOutputPort*>"(CPort*)
+
+cdef extern from "music/setup.hh" namespace "MUSIC":
+    cdef cppclass CSetup "MUSIC::Setup":
+        CSetup(int&, char**&) except +
+        CSetup(int&, char**&, int, int*) except +
+
+        cbool config(string, string*)
+
+        CContInputPort*     publishContInput(string)
+        CContOutputPort*    publishContOutput(string)
+        CEventInputPort*    publishEventInput(string)
+        CEventOutputPort*   publishEventOutput(string)
+        CMessageInputPort*  publishMessageInput(string)
+        CMessageOutputPort* publishMessageOutput(string)
+
+cdef extern from "music/runtime.hh" namespace "MUSIC":
+    cdef cppclass CRuntime "MUSIC::Runtime":
+        CRuntime(CSetup*, double) except +
+        void finalize()
+        double time()
+        void tick()
+
+cdef extern void cython_callback(PyObject*, double, IndexType, int)
+
+cdef extern from "music/music_c.h" namespace "MUSIC":
+    cdef inline MPI_Comm communicator(CSetup*)
+    cdef inline MPI_Comm communicator(CRuntime*)
+    cdef inline int toint(GlobalIndex)
+    cdef inline int toint(LocalIndex)
+    cdef inline cbool tick(CRuntime*) except False
+    cdef inline CEventHandlerPtr getEventHandlerPtr(IndexType, CEventHandler*)
+
+    cdef inline void mapImpl "MUSIC::Implementer::mapImpl" (
+        CContInputPort*, CDataMap*, double, int, cbool)
+    cdef inline void mapImpl "MUSIC::Implementer::mapImpl" (
+        CContOutputPort*, CDataMap*, int)
+    cdef inline void mapImpl "MUSIC::Implementer::mapImpl" (
+        CEventInputPort*, CIndexMap*, IndexType, 
+        CEventHandlerPtr, double, int)
+    cdef inline void mapImpl "MUSIC::Implementer::mapImpl" (
+        CEventOutputPort*, CIndexMap*, IndexType, int)
+    cdef inline void insertEventImpl "MUSIC::Implementer::insertEventImpl" (
+        CEventOutputPort*, double, int)
+    cdef inline void mapImpl "MUSIC::Implementer::mapImpl" (
+        CMessageInputPort*, CMessageHandler*, double, int)
+    cdef inline void mapImpl "MUSIC::Implementer::mapImpl" (
+        CMessageOutputPort*, int)
+    cdef inline void insertMessage "MUSIC::Implementer::insertMessage" (
+        CMessageOutputPort*, double t, void*, size)
+
+    cdef cbool pythonError
+    cdef PyObject* etype
+    cdef PyObject* evalue
+    cdef PyObject* etraceback
+    
+
+###########################################################
+
+cdef class Setup(object):
+    cdef CSetup* ptr
+    cdef list argv
+    cdef int provided
+    cdef readonly MPI.Intracomm comm
+    cdef set ports
+
+    cdef null(self)
+    cpdef MPI.Intracomm getcomm(self)
+
+###########################################################
+
+cdef class Runtime(object):
+    cdef CRuntime* ptr
+    cdef readonly MPI.Intracomm comm
+    cdef set ports
+
+###########################################################
+
+cdef class Port(object):
+    cdef CPort* ptr
+    cpdef object null(self)
+
+## Some day, virtual multiple inheritance will be
+## a capital crime ^^^^
+
+cdef class ContInputPort(Port):
+    pass
+
+cdef class ContOutputPort(Port):
+    pass
+
+cdef class EventInputPort(Port):
+    cdef set events
+    cpdef object null(self)
+
+cdef class EventOutputPort(Port):
+    pass
+
+cdef class MessageInputPort(Port):
+    cdef set events
+    cpdef object null(self)
+
+cdef class MessageOutputPort(Port):
+    cdef bint pickled
+
+##########################################################
+
+from music.pybuffer cimport Buffer
+
+cdef class DataMap(object):
+    cdef CDataMap* ptr
+    cdef Buffer buf
+
+cdef class IndexMap(object):
+    cdef CIndexMap* ptr
+    cdef Buffer buf
+
+cdef class EventHandler:
+    cdef CEventHandler* ptr
+    cdef object func
+
+cdef class MessageHandler:
+    cdef CMessageHandler* ptr
+    cdef object func
+
+cdef cbool EventCallback "MUSIC::EventCallback" ( \
+  PyObject*, double, IndexType, int) except False
+
+cdef cbool MessageCallback "MUSIC::MessageCallback" ( \
+  PyObject*, double, void*, size_t, cbool) except False
diff --git a/pymusic/pymusic.pyx b/pymusic/pymusic.pyx
new file mode 100644
index 0000000..922a2a1
--- /dev/null
+++ b/pymusic/pymusic.pyx
@@ -0,0 +1,728 @@
+#
+# distutils: language = c++
+# cython: c_string_encoding = default
+
+from libc.stdlib cimport malloc, free
+
+import mpi4py.MPI as MPI
+import cPickle as pickle
+
+###########################################################
+
+class MUSICError(Exception):
+    """
+    All exceptions in pymusic are MUSICError's
+    """
+    pass
+
+class NoWidth(MUSICError):
+    """
+    Thrown if Port.width() is called, and port doesn't
+    have a width defined.
+    """
+    def __init__(self):
+        MUSICError.__init__(self, "No width defined")
+
+class UndefinedConfig(MUSICError):
+    """
+    Thrown if a configuration value is requested
+    via Setup.config(varname) for a variable name
+    that has not been defined within the configuration.
+    """
+    def __init__(self, var):
+        MUSICError.__init__(
+            self,
+            "Config variable {} is not defined".
+            format(var)
+        )
+
+###########################################################
+
+# """
+# Just pass args as a named tuple for C functions that
+# take the command line parameters:
+#   int argc
+#   char** argv
+# argv = [exec, op[1], ..., op[argc-1], NULL]
+# """
+ctypedef struct Args:
+    int argc
+    char** argv
+
+cdef Args argv_toc(list argv):
+    """
+    Convert an argv python list to a correct C argv & argc
+    values with null termination, returned as an Args tuple
+    """
+    cdef Args r
+    r.argc = len(argv)
+    if r.argc <= 0:
+        raise MUSICError("argv can't be empty")
+
+    r.argv = <char**> malloc((r.argc+1) * sizeof(char*))
+    if r.argv is NULL:
+        raise MUSICError("couldn't allocate argv")
+
+    cdef string
+    try:
+        r.argv[r.argc] = NULL
+        for i in range(0, r.argc):
+            s = argv[i].encode()
+            r.argv[i] = s
+        return r
+    except:
+        free(r.argv)
+        raise
+
+###########################################################
+
+def predictRank(list argv=None):
+    """
+    Map into mpidep/predict_rank for config methods.
+    AP: What is this really used for?
+    """
+    cdef Args r = argv_toc(argv if argv is not None else
+                           sys.argv)
+    return CPredictRank(r.argc, r.argv)
+
+###########################################################
+
+cdef class Port(object):
+    """
+    Base Port class.
+
+    The underlying pointer is not deallocated here, since in MUSIC the
+    port is owned by Setup/Runtime.  This does null the value when we
+    believe the underlying object may be deallocated by the
+    container.
+    """
+    def __cinit__(self):
+        """
+        When a Port object is created, it needs to have an underlying
+        C++ class assigned to ptr from a Setup.publish* method.
+        """
+        self.ptr = NULL
+
+    def __hash__(self):
+        """
+        Hash function: pointer value % to an int.
+        """
+        return <int><size_t> self.ptr
+
+    cpdef null(self):
+        """
+        When Setup or Runtime no longer needs ports and so may deallocate
+        them, we first must clear the references to them here. This
+        may be overridden to give up references to other members by
+        the descendants
+        """
+        self.ptr = NULL
+
+    def isConnected(self):
+        """
+        return True iff the port is actually connected via the config
+        file.
+        """
+        return self.ptr.isConnected()
+
+    def width(self):
+        """
+        Returns the width set in the MUSIC config file
+        which defines the number of indices transferred
+        along this port. If no width is defined, raise a NoWidth
+        exception.
+        """
+        if not self.ptr.hasWidth(): raise NoWidth()
+        return self.ptr.width()
+
+cdef class ContInputPort(Port):
+    """
+    ContInputPort maps data indices between sources and sinks. This is
+    the sink side; source is ContOutputPort. Created by
+    Setup.publishContInputPort(portname).
+    """
+    def map(self,
+            object data,
+            int base=0,
+            object perm=None,
+            double delay=0,
+            cbool interpolate=True,
+            int maxBuffered=-1):
+        """
+        map data as source for this port. (Can you do a multiple mapping?)
+
+        object data: object to be shared that has a buffer interface.
+                     That interface needs to be contiguous formed of
+                     simple items that can be mapped to simple MPI
+                     data types.
+        int base (=0), object perm (=None): used to construct an
+                     IndexMap (with number of items in data). See that
+                     class for more information. Defines mapping for data
+                     between this input source and the output sinks.
+        double delay (=0): this is the delay of measurement relative
+                           to "something" which I haven't been able to
+                           figure out yet --- needs to be explained.
+        interpolate (=True): whether to do a linear interpolation of
+                             the values that are being delayed. Once
+                             again, needs to be better explained.
+        maxBuffered (=-1): buffer up to maxBuffered ticks. If -1, use
+                           a "reasonable value" (???).  What does this
+                           mean on the input side?
+        """
+        cdef Buffer buf = Buffer(data)
+        cdef IndexMap imap = IndexMap(perm, base, buf.items)
+        cdef DataMap d = DataMap(buf, imap)
+        cdef CContInputPort* ptr = dc_CContInputPort(self.ptr)
+        mapImpl(ptr, d.ptr, delay, maxBuffered, interpolate)
+
+cdef class ContOutputPort(Port):
+    """
+    ContOutputPort maps data indices between sources and sinks. This
+    is the source side; ContInputPort is the sink. Created by
+    Setup.publishContOutputPort(portname).
+    """
+    def map(self, object data,
+            int base=0, object perm=None,
+            int maxBuffered=-1):
+        """
+        map data as sink for this port. (Can you do a multiple mapping?)
+
+        object data: object to be shared that has a buffer interface.
+                     That interface needs to be contiguous formed of
+                     simple items that can be mapped to simple MPI
+                     data types.
+        int base (=0), object perm (=None): used to construct an
+                     IndexMap (with number of items in data). See that
+                     class for more information. Defines mapping for data
+                     between this input source and the output sinks.
+        maxBuffered (=-1): buffer up to maxBuffered ticks. If -1, use
+                     a "reasonable value" (???).
+        """
+        cdef Buffer buf = Buffer(data)
+        cdef IndexMap imap = IndexMap(perm, base, buf.items)
+        cdef DataMap d = DataMap(buf, imap)
+        cdef CContOutputPort* ptr = dc_CContOutputPort(self.ptr)
+        mapImpl(ptr, d.ptr, maxBuffered)
+
+cdef class EventInputPort(Port):
+    """
+    Event sink. Maps 'events' to handlers. Events are spike-like
+    events at a defined time associated with an id, either/or
+    global/local in some (unclear to me) way.
+
+    Since these 'events' must be protected from deallocation as long
+    as the port exists (until finalization), we keep a set of them
+    here and drop the reference when this object is null'd (events member).
+    """
+    def __cinit__(self):
+        """
+        Store a set of references to the event handlers
+        """
+        self.events = set()
+
+    cpdef null(self):
+        """
+        Not just null pointer, but give up the associated event
+        handlers.
+        """
+        Port.null(self)
+        self.events = None
+
+    def map(self, func, IndexType t,
+            double accLatency=0, int maxBuffered=-1,
+            object perm=None, int base=-1, int size=-1):
+        """
+        Map events to this sink.
+        func is:
+          void func(double value, IndexType GLOBAL|LOCAL, int index)
+        IndexType is (?) the index type to map the incoming sources
+            passed to the func (why, if we already know this?)
+        accLatency is the delivery delay relative to calculation time
+            (? is it ? What formula are we using here?)
+        maxBuffered is ticks to buffer
+        perm, base & size are passed to IndexMap
+        """
+        cdef IndexMap imap = IndexMap(perm, base, size)
+        cdef EventHandler eh = EventHandler(func, t)
+        cdef CEventInputPort* ptr = dc_CEventInputPort(self.ptr)
+        cdef CEventHandlerPtr hndl = getEventHandlerPtr(t, eh.ptr)
+        mapImpl(ptr, imap.ptr, t, hndl, accLatency, maxBuffered)
+        self.events.add(eh)
+
+cdef class EventOutputPort(Port):
+    """
+    Map events from this sink. See EventInputPort for description of
+    events.
+    """
+    def map(self, IndexType t, int maxBuffered=-1,
+            object perm=None, int base=-1, int size=-1):
+        """
+        IndexType: LOCAL/GLOBAL
+        maxBuffered: tick to buffer (why on both sides?)
+        perm, base, size: define IndexMap (see that class)
+        """
+        cdef IndexMap m = IndexMap(perm, base, size)
+        cdef CEventOutputPort* ptr = dc_CEventOutputPort(self.ptr)
+        mapImpl(ptr, m.ptr, t, maxBuffered)
+
+    def insertEvent(self, double time, int index, IndexType t):
+        """
+        double time: time of event (must be during current tick)
+        int index: local or global index of event
+        IndexType t: LOCAL|GLOBAL
+        """
+        cdef CEventOutputPort* ptr = dc_CEventOutputPort(self.ptr)
+        insertEventImpl(ptr, time, index)
+
+cdef class MessageInputPort(Port):
+    """
+    Maps 'events' to handlers.
+
+    Since these 'events' must be protected from deallocation as long
+    as the port exists (until finalization), we keep a set of them
+    here and drop the reference when this object is null'd.
+    """
+    def __cinit__(self):
+        self.events = set()
+
+    cpdef null(self):
+        """
+        Remember to remove the references to events...
+        """
+        Port.null(self)
+        self.events = None
+
+    def map(self, func, double accLatency=0, int maxBuffered=-1, bint pickled=True):
+        """
+        The message handling function.
+        func: callable object as follows
+           void func(double time, object msg):
+             time: the set insertion time of the message
+             msg: an object which may have been pickled and fed through music
+        accLatency(0): "acceptable latency" (???)
+        maxBuffered(-1): ticks that can be buffered (-1 means unknown
+           amount (???))
+        pickled(True): pickle objects on both ends; else, the object should be
+                       a buffer object and we'll receive a bytearray
+        """
+        cdef MessageHandler eh = MessageHandler(func, pickled)
+        cdef CMessageInputPort* ptr = dc_CMessageInputPort(self.ptr)
+        mapImpl(ptr, eh.ptr, accLatency, maxBuffered)
+        self.events.add(eh)
+
+cdef class MessageOutputPort(Port):
+    """
+    The source of "messages". A message is a python object that is
+    pickled and fed to the other end, associated with a time.
+    """
+    def map(self, int maxBuffered=-1, bint pickled=True):
+        """
+        map only sets the buffering ticks.
+        maxBuffered (-1): ticks to buffer (-1 means "reasonable" ???)
+        pickled (True): whether messages objects inserted her are automatically
+                        pickled, else the object should be a buffer-type and
+                        the other end will get a bytearray.
+        """
+        self.pickled = pickled
+        cdef CMessageOutputPort* ptr = dc_CMessageOutputPort(self.ptr)
+        mapImpl(ptr, maxBuffered)
+
+    def insertMessage(self, double time, object msg):
+        """
+        insert a python object as a message at a time during the
+        current tick.
+        time: ms times (??)
+        msg: a python object that can be cPickled if self.pickled == True
+             else something that has a buffer interface.
+        """
+        cdef CMessageOutputPort* ptr = dc_CMessageOutputPort(self.ptr)
+        cdef bytearray pmsg =                                           \
+                <bytearray> pickle.dumps(msg, pickle.HIGHEST_PROTOCOL)  \
+                if self.pickled                                         \
+                else <bytearray> msg
+        ptr.insertMessage(time, <char*> pmsg, len(pmsg))
+
+###########################################################
+
+import sys
+cdef class Setup(object):
+    """
+    API to setup the music interface.
+    Becomes invalid after a Runtime object is created.
+    It gives access to config variables (*.music file),
+    and creates sinks and sources which can then be configured with
+    the respective map method of each.
+    """
+
+    def __cinit__(self, list argv=None, required=None):
+        """
+        Takes the command line arguments and the required threading
+        level.
+        string[] argv (None): comand line args; if None, use sys.argv
+        int required (None): the MPI threading level for MPI-2. If
+        None, don't set at all, but provided level in object set to
+        MPI_THREAD_SINGLE. Also stores command line arguments.
+        Calls CSetup object and connects with communicator.
+        """
+
+        cdef int argc
+        cdef char** argv_c
+        cdef int provided
+
+        cdef Args r = argv_toc(argv if argv is not None
+                               else sys.argv)
+        try:
+            if required is None:
+                self.ptr = new CSetup(r.argc, r.argv)
+                self.provided = MPI_THREAD_SINGLE
+            else:
+                self.ptr = new CSetup(r.argc, r.argv, required, &provided)
+                self.provided = provided
+            self.argv = [r.argv[i] for i in xrange(r.argc)]
+        finally:
+            free(r.argv)
+
+        cdef MPI.Intracomm comm = MPI.Intracomm()
+        comm.ob_mpi = communicator(self.ptr)
+        self.comm = comm
+
+        self.ports = set()
+
+    def __dealloc__(self):
+        """
+        If runtime has been made and setup is invalid, do nothing.
+        Otherwise, deallocate or remove references to all objects.
+        """
+
+        if self.ptr is NULL:
+            return
+
+        del self.ptr
+        for p in self.ports:
+            del p.ptr
+            p.null()
+        self.null()
+
+    cpdef MPI.Intracomm getcomm(self):
+        """
+        Get an MPI communicator between the processes on this current
+        side of music
+        """
+        return self.comm
+
+    cdef null(self):
+        """
+        Invalidate this object --- called when runtime is
+        created. Music & runtime is now responsible for deallocating C
+        objects and clearing references to them.
+        """
+        self.ptr = NULL
+        self.comm = <MPI.Intracomm> MPI.COMM_NULL
+        self.ports = None
+
+    ####
+    def config(self, string var):
+        """
+        Get the value for var in config file.
+        string var: configuration variable for current group of
+        processes, including default and inherited settings.
+        The value is returned as an int if it matches the patter,
+        otherwise a float, otherwise a string.
+        Throws UndefinedConfig error if no such variable is defined.
+        """
+        cdef string vs
+
+        if not self.ptr.config(var, &vs):
+            raise UndefinedConfig(var)
+
+        try: return int(vs)
+        except ValueError: pass
+
+        try: return float(vs)
+        except ValueError: pass
+
+        return vs
+    ####
+
+    def publishContInput(self, string s):
+        """
+        Continuous Floating point value sink
+        string s: port name for music config
+        """
+        cdef ContInputPort p = ContInputPort()
+        p.ptr = self.ptr.publishContInput(s) # can't pass pointers directly to init
+        self.ports.add(p)
+        return p
+
+    def publishContOutput(self, string s):
+        """
+        Continuous Floating point value source
+        string s: port name for music config
+        """
+        cdef ContOutputPort p = ContOutputPort()
+        p.ptr = self.ptr.publishContOutput(s)
+        self.ports.add(p)
+        return p
+
+    def publishEventOutput(self, string s):
+        """
+        Discrete boolean source
+        string s: port name for music config
+        """
+        cdef EventOutputPort p = EventOutputPort()
+        p.ptr = self.ptr.publishEventOutput(s)
+        self.ports.add(p)
+        return p
+
+    def publishEventInput(self, string s):
+        """
+        Discrete boolean sink
+        string s: port name for music config
+        """
+        cdef EventInputPort p = EventInputPort()
+        p.ptr = self.ptr.publishEventInput(s)
+        self.ports.add(p)
+        return p
+
+    def publishMessageOutput(self, string s):
+        """
+        Discrete python object source
+        string s: port name for music config
+        """
+        cdef MessageOutputPort p = MessageOutputPort()
+        p.ptr = self.ptr.publishMessageOutput(s)
+        self.ports.add(p)
+        return p
+
+    def publishMessageInput(self, string s):
+        """
+        Discrete python object sink
+        string s: port name for music config
+        """
+        cdef MessageInputPort p = MessageInputPort()
+        p.ptr = self.ptr.publishMessageInput(s)
+        self.ports.add(p)
+        return p
+
+    def runtime(self, double timestep):
+        """
+        Create a runtime.
+        After return, this Setup object is invalid
+        double timestep: size of timestep (?? units)
+        """
+        return Runtime(self, timestep)
+
+###########################################################
+
+cdef class Runtime(object):
+    def __cinit__(self, Setup setup, double h):
+        self.ptr = new CRuntime(setup.ptr, h)
+        self.ports = setup.ports
+        setup.null()
+
+        cdef MPI.Intracomm comm = MPI.Intracomm()
+        comm.ob_mpi = communicator(self.ptr)
+        self.comm = comm
+
+    def __dealloc__(self):
+        self.ptr.finalize()
+
+        for p in self.ports:
+            p.null()
+
+        del self.ptr
+
+    def time(self): return self.ptr.time()
+    def tick(self): tick(self.ptr)
+
+    def __iter__(self):
+        cdef CRuntime* ptr = self.ptr
+        while True:
+            yield ptr.time()
+            tick(ptr)
+
+###########################################################
+
+from music.pybuffer import Buffer
+
+from cpython cimport array
+from array import array
+
+cdef class IndexMap:
+    """
+    Internal:
+    Contains a C++ LinearIndex or PermutationIndex.
+    These map between "local" index i to "global" index j
+    LinearIndex: g = l + base, for l < size
+    PermutationIndex: g = perm[l], where perm is an array
+    """
+    def __cinit__(self, object perm=None, int base=0, int size=-1):
+        """
+        Created internally
+        Either perm is None, or we have a base, size pair
+        perm is buffer of integers mapping local to global
+          (local[i] -> global[perm[i]])
+        otherwise base is the first global index for size elements
+          (local[0] -> global[base])
+        """
+        cdef array.array arr
+
+        if perm is None:
+            self.buf = None
+            self.ptr = new LinearIndex(GlobalIndex(base), size)
+        else:
+            self.buf = Buffer(perm)
+            if self.buf.dtype.size() != sizeof(int):
+                arr = array('i', perm)
+                self.buf = Buffer(arr)
+            self.ptr = new PermutationIndex(<GlobalIndex*>
+                                            self.buf.pybuf.buf,
+                                            self.buf.items)
+
+    def __dealloc__(self):
+        del self.ptr
+
+cdef class DataMap(object):
+    """
+    Internal:
+    An ArrayData object. Takes a data object as a Buffer and possibly an
+    IndexMap to construct a mapping for the Cont*Port transfers.
+    """
+    def __cinit__(self, Buffer buf, IndexMap index_map=None, int index=0):
+        """
+        Maps the Buffer of a data object between local and global indices.
+        Buffer buf: some simple array type that will be pushed through mpi
+        IndexMap index_map (None): an option index mapping from local to global
+        index (0): if index_map is None, this is the base offset for constructing
+                   a linear index
+        """
+        self.buf = buf
+        self.ptr = new CArrayData(buf.pybuf.buf,
+                                  buf.dtype.ob_mpi,
+                                  index, buf.items) \
+                   if index_map is None else \
+                   new CArrayData(buf.pybuf.buf,
+                                  buf.dtype.ob_mpi,
+                                  index_map.ptr)
+
+    def __dealloc__(self): del self.ptr
+
+cdef class EventHandler:
+    """
+    Internal:
+    An EventHandler is the python wrapper around a global
+    or local EventHandler object for EventInputPort
+    """
+    def __cinit__(self, object func, IndexType t):
+        """
+        func: a callable of the form
+          func(double d, IndexType t, int i) where 
+             double d: the event time
+             IndexType t: local or global index enum
+             int i: the index value
+        IndexType t: the IndexType to receive in func
+             (??? Why is this so complex?? Do we need
+              to generalize func like this??)
+        """
+        self.ptr = <CEventHandler*>                \
+                   new CEHGlobal(<PyObject*>func) \
+                   if t == IndexGLOBAL else       \
+                   <CEventHandler*>               \
+                   new CEHLocal(<PyObject*>func)
+        self.func = func
+
+    def __dealloc__(self): del self.ptr
+
+cdef class _Index:
+    """
+    Internal: the type of the variable Index
+    that encapsulates the enum mapping
+    GLOBAL and LOCAL are the ints of the C enums
+    backmap maps from the enum to a string for output
+    purposes
+    """
+    cdef readonly int GLOBAL
+    cdef readonly int LOCAL
+    cdef readonly dict backmap
+
+    def __cinit__(self):
+        """ SINGLETON """
+        self.GLOBAL = IndexGLOBAL
+        self.LOCAL = IndexLOCAL
+        self.backmap = {
+            IndexGLOBAL: "GLOBAL",
+            IndexLOCAL: "LOCAL"
+        };
+
+    def tostr(self, int index):
+        """" tostring(Index.{GLOBAL,LOCAL}) --> "{GLOBAL,LOCAL}" """
+        return self.backmap[index]
+
+# And here is the singleton def
+Index = _Index()
+
+cdef cbool EventCallback(PyObject* func,
+                         double d,
+                         IndexType t,
+                         int i) \
+    except False:
+    """
+    Internal: C code can map back into python through this callback
+    func: callable object of func(d, t, i)
+    double d: time of event
+    IndexType t: LOCAL/GLOBAL int
+    int i: index of event
+    """
+    (<object>func)(d, t, i)
+    return True
+
+cdef class MessageHandler:
+    """
+    MessageHandler wraps up Message*Port communications between C & python,
+    wrapping n particular the C++ MessageHandler object bound with a function.
+    It may (or may not) depickle messages
+    """
+    def __cinit__(self, object func, bint pickled):
+        """
+        func: The function to be called on a message, of the form
+          func(double t, object msg) where:
+            double t: the message time
+            msg: Either a bytearray, or an arbitrary unpickled python object
+        pickled: if true, the msg needs to be depickled
+        """
+        self.ptr = new CMHandler(<PyObject*>func, pickled)
+        self.func = func
+
+    def __dealloc__(self):  del self.ptr
+
+cdef cbool MessageCallback(PyObject* func,
+                           double t,
+                           void* msg,
+                           size_t s,
+                           cbool pickled) \
+    except False:
+    """
+    The function to return a Message from C to Python.
+    func: callable of the form
+       func(double t, object/bytearray obj) where:
+         t: is the time of the message
+         obj: is either the unpickled object if the port unpickles
+              or simply a bytearray of data (you figure out the source)
+    """
+    cdef str pobj = (<char*>msg)[:s]
+    cdef object obj = pickle.loads(pobj) if pickled else <bytearray> pobj
+    (<object>func)(t, obj)
+    return True
+
+#############################################################################
+#
+# And for handling errors at the C/Python interface
+#
+# pythonError: true if a python error is being stored until we get out of C
+# etype, evalue, etraceback: three bits of data to recreate the exception 
+#    so that it can be thrown
+#
+pythonError = False
+etype = NULL
+evalue = NULL
+etraceback = NULL
diff --git a/pymusic/setup.py.in b/pymusic/setup.py.in
new file mode 100644
index 0000000..b73ada0
--- /dev/null
+++ b/pymusic/setup.py.in
@@ -0,0 +1,13 @@
+from distutils.core import setup
+
+setup(
+    name='@PACKAGE_NAME@',
+    version='@PACKAGE_VERSION@',
+    description='pyMUSIC provides Python bindings for MUSIC',
+    author='Alexander Peyser',
+    author_email='a.peyser@fz-juelich.de',
+    url='unknown',
+    license='GPLv2+',
+    packages=['music'],
+    package_dir={'music': '@top_srcdir@/pymusic/music'}
+)
diff --git a/rudeconfig/.gitignore b/rudeconfig/.gitignore
new file mode 100644
index 0000000..736099e
--- /dev/null
+++ b/rudeconfig/.gitignore
@@ -0,0 +1,5 @@
+/Makefile
+/Makefile.in
+/TAGS
+/.deps
+/core
diff --git a/rudeconfig/AUTHORS b/rudeconfig/AUTHORS
new file mode 100644
index 0000000..857c9c3
--- /dev/null
+++ b/rudeconfig/AUTHORS
@@ -0,0 +1,35 @@
+Authors of RudeConfig C++ Library
+
+For correspondence specific to the rudeconfig library, 
+please use the email address <rudeconfig@rudeserver.com>
+
+RudeConfig was written by Matt Flood <matt@rudeserver.com>
+RudeConfig is currently maintained by Matt Flood
+
+In the US:
+ Matt Flood
+ Unit 114
+ 4820 Thunderbird Circle
+ Boulder, CO 80303
+ (+1) (720) 284-1208
+ http://www.rudeserver.com/
+
+Copyright (C) 2005 Matthew Flood
+
+This file is part of RudeConfig.
+
+RudeConfig 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; either version 2, or (at your option)
+any later version.
+
+RudeConfig 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 should have received a copy of the GNU General Public License
+along with RudeConfig; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
diff --git a/rudeconfig/COPYING b/rudeconfig/COPYING
new file mode 100644
index 0000000..623b625
--- /dev/null
+++ b/rudeconfig/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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; either version 2 of the License, or
+    (at your option) any later version.
+
+    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 should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/rudeconfig/ChangeLog b/rudeconfig/ChangeLog
new file mode 100644
index 0000000..d0b25c7
--- /dev/null
+++ b/rudeconfig/ChangeLog
@@ -0,0 +1,201 @@
+2009-10-24  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* src/ParserJuly2004.cpp: #include <cstdio>.
+	(ParserJuky2004::parse): Changed type of variable `dotPos' from
+	int to size_t throughout; Use '&&' instead of '&' in conditional
+	expression.
+
+2009-03-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am (man_MANS): Don't install man pages.
+	(pkginclude): Don't install header files.
+
+2009-02-11  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am: Changed librudeconfig.la to a noinst target.
+
+2008-08-05  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* src/ConfigImpl.cpp: #include <cstring>.
+
+	* src/File.h: #include <string>.
+
+2007-11-07  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* ParserJuly2004.cpp: Use int instead of char to handle parsed
+	characters, so that we can distinguish between code 255 and EOF.
+
+2007-11-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* INSTALL, Makefile.in, aclocal.m4, config.guess, config.sub,
+	configure.ac, configure, depcomp, install-sh, ltmain.sh, missing:
+	Removed.
+
+2007-11-01  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* src/config.h, src/config.cpp (Config::load): Added new method
+	for std::istream&.
+
+ ChangeLog for RudeConfig C++ Library
+
+ Copyright (C) 2005, 2007, 2008 Matthew Flood
+ See file AUTHORS for contact information
+
+ This file is part of RudeConfig.
+
+ RudeConfig 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; either version 2, or (at your option)
+ any later version.
+ 
+ RudeConfig 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 should have received a copy of the GNU General Public License
+ along with RudeConfig; (see COPYING) if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+* Thu Feb 01 2007 Matt Flood <matt@rudeserver.com>
+- 5.0.5-1
+- Renamed header include guards in config.h
+	- From INCLUDED_CONFIG_H to INCLUDED_RUDE_CONFIG_H
+
+* Thu Feb 01 2007 Matt Flood <matt@rudeserver.com>
+- 5.0.4-3
+- Minor amendments to build-related scripts
+	- Added missing include directory to specfile
+
+* Thu Feb 01 2007 Matt Flood <matt@rudeserver.com>
+- 5.0.4-2
+- Minor amendments to build-related scripts
+	- Fixed minor typo in changelog (ChangeLog and rudeconfig.spec)
+	- Added --disable-static to configure directive in rudeconfig.spec
+
+* Fri Jan 19 2007 Matt Flood <matt@rudeserver.com>
+- 5.0.4-1
+- Created MAN page (rudeconfig.3)
+
+* Mon Jul 31 2006 Matt Flood <matt@rudeserver.com>
+-  5.0.3-1
+- Minor changes to facilitate Windows builds 
+		* changed #include's of  <cstring> to <string.h>
+		* added .c_str() to a string object to correct shorthand if statement ( a ? x : y )
+
+* Thu Apr 10 2006 Matt Flood <matt@rudeserver.com>
+- 5.0.2-1
+- First RPM Release
+
+* Fri Sep 2 2005 Matt Flood <matt@rudeserver.com>
+- 5.0.2-0
+- Modified source code for DataLine.cpp - removed 'using namespace std' which Visual Studio is too dumb to ignore.
+- Fixed ParserJuly2004::chompEOL() - was not returning a value - (TODO: consider making the function void)
+
+
+-------------
+--------------------------
+---------------------------------------------------
+Release Version 3.2  Lib Version 5.0.2
+
+2005-06-02
+	* Renamed Config.cc to config.cc - interface files will be lower case, all other will remain mixed-cased.
+	* Added Instance Methods:
+			const char *Config::getConfigFile();
+			const char *ConfigImpl::getConfigFile();
+	* In order to accommodate windows builds, renamed *.cc to *.cpp
+
+
+-------------
+--------------------------
+---------------------------------------------------
+Release Version 3.1  Lib Version 4.0.1
+	
+			
+2005-05-18
+	*	Renamed Config.h config.h
+
+2005-05-17 Matthew Flood
+	* Changed signature of:
+	
+			static int ConfigImpl::stringToBinary(const char *value, char *dataout);
+
+			to: 
+			
+			static char * ConfigImpl::stringToBinary(const char *value, int &outlength);
+
+
+2005-05-07 Matthew Flood
+	*Added the folowing interface methods
+			const char * Config::getValue(const char *name) const;
+			void Config::setValue(const char *name, const char *value);
+	*getStringValue() and setStringValue() are now deprecated
+
+2005-05-06 Matthew Flood
+
+	*Added AUTOMAKE_OPTIONS to create more distribution types
+	*Created README, THANKS, NEWS
+	*Added Static Interface methods:
+			static void Config::setDefaultConfigFile(const char *filepath);
+			static const char *Config::getDefaultConfigFile();
+			static void Config::setDefaultCommentCharacter(char c);
+			static char Config::getDefaultCommentCharacter();
+			static void Config::setDefaultDelimiter(char c);
+			static char Config::getDefaultDelimiter();
+			static void Config::setDefaultPreserveDeleted(bool shouldPreserve);
+			static bool Config::getDefaultPreserveDeleted();
+	*Added Static Implementation Methods (Implementation Additions)
+			static const char *ConfigImpl::getDefaultConfigFile();
+			static char ConfigImpl::getDefaultCommentCharacter();
+			static char ConfigImpl::getDefaultDelimiter();
+			static bool ConfigImpl::getDefaultPreserveDeleted();
+	*Updated API Documentation
+
+
+-------------
+--------------------------
+---------------------------------------------------
+Release Version 3.0 Lib Version 3.0.0
+
+2005-05-05  Matthew Flood  (Created Open Source)
+
+	* AUTHORS - created
+	* ChangeLog Created
+	* Renamed config.h and config.cc to Config.h and Config.cc
+
+
+-------------
+--------------------------
+---------------------------------------------------
+Release 2.1
+
+1. Added setSection(const char *) method to interface, to replace the 
+	commonly used setSection(const char *, bool) 
+2. Added preserveDeletedData(bool) method to allow deleted data to be discarded 
+3. Made significant performance optimizations
+4. Enhanced documentation 
+5. Changed name of default configuration file from default.cnf to default.ini 
+
+
+-------------
+--------------------------
+---------------------------------------------------
+Release 1.1
+
+1. Fixed integer and double conversion bugs 
+
+
+-------------
+--------------------------
+---------------------------------------------------
+Release 1.0
+
+1. Renamed Component from Rude_Config 
+2. Added Rude namespace 
+3. Added multi-line value support (backslash-CRLF escape sequence) 
+
+
+------------------------------------------------------------------------------------
+
+--End of Change Log--
diff --git a/rudeconfig/Makefile.am b/rudeconfig/Makefile.am
new file mode 100644
index 0000000..06074b1
--- /dev/null
+++ b/rudeconfig/Makefile.am
@@ -0,0 +1,70 @@
+# Makefile.am
+#
+# Copyright (C) 2005 Matthew Flood
+# See file AUTHORS for contact information
+#
+# This file is part of RudeConfig.
+#
+# RudeConfig 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; either version 2, or (at your option)
+# any later version.
+# 
+# RudeConfig 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 should have received a copy of the GNU General Public License
+# along with RudeConfig; (see COPYING) if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+#------------------------------------------------------------------------
+AUTOMAKE_OPTIONS = gnits dist-bzip2 dist-zip subdir-objects
+
+noinst_LTLIBRARIES = librudeconfig.la 
+librudeconfig_la_SOURCES = src/AbstractData.cpp \
+	src/Comment.cpp \
+	src/File.cpp \
+	src/Section.cpp \
+	src/AbstractOrganiser.cpp \
+	src/config.cpp \
+	src/KeyValue.cpp \
+	src/WhiteSpace.cpp \
+	src/AbstractParser.cpp \
+	src/ConfigImpl.cpp \
+	src/Writer.cpp \
+	src/SourceDest.cpp \
+	src/AbstractWriter.cpp \
+	src/DataLine.cpp \
+	src/ParserJuly2004.cpp \
+	src/Base64Encoder.cpp \
+	src/RealOrganiser.cpp \
+	src/AbstractData.h \
+	src/AbstractWriter.h \
+	src/config.h \
+	src/Section.h \
+	src/AbstractOrganiser.h \
+	src/Base64Encoder.h \
+	src/ConfigImpl.h \
+	src/File.h \
+	src/ParserJuly2004.h \
+	src/WhiteSpace.h \
+	src/AbstractParser.h \
+	src/Comment.h \
+	src/DataLine.h \
+	src/KeyValue.h \
+	src/RealOrganiser.h \
+	src/Writer.h \
+        src/SourceDest.h
+
+librudeconfig_la_LDFLAGS = -version-info 5:1:2
+
+#pkginclude_HEADERS = src/config.h
+#pkgincludedir = $(includedir)/rude
+
+#man_MANS = man3/rudeconfig.3
+
+EXTRA_DIST = $(man_MANS)
+
+
diff --git a/rudeconfig/NEWS b/rudeconfig/NEWS
new file mode 100644
index 0000000..20c5283
--- /dev/null
+++ b/rudeconfig/NEWS
@@ -0,0 +1,114 @@
+RudeConfig NEWS - User visible changes.
+See ChangeLog for more detailed information on internal changes
+See the end for copying conditions.
+
+_______________________________________________________________________________
+Release 5.0.5-1 - Matthew Flood 2007-02-01
+
+	- Renamed header include guards in config.h from 
+	  INCLUDED_CONFIG_H to INCLUDED_RUDE_CONFIG_H
+	  The new guards are less generic and safer to use overall. 
+
+_______________________________________________________________________________
+Release 5.0.4-3 - Matthew Flood 2007-02-01
+
+	- Minor amendments to build-related scripts
+
+_______________________________________________________________________________
+Release 5.0.4-2 - Matthew Flood 2007-02-01
+
+	- Minor amendments to build-related scripts
+
+_______________________________________________________________________________
+Release 5.0.4-1 - Matthew Flood 2007-01-19
+
+	- Created rudeconfig.3 MAN page
+ 		* To access the rudeconfig manual from your linux command prompt, 
+                  use the man command:
+                  
+                     $>man rudeconfig
+			OR
+		     $>man 3 rudeconfig
+
+_______________________________________________________________________________
+Release 5.0.3-1 - Matthew Flood 2006-07-31
+
+	- Changed versioning system again.  
+	- Minor changes to facilitate Windows builds
+		* changed #include's of  <cstring> to <string.h>
+		* added .c_str() to a string object to correct shorthand if statement ( a ? x : y )
+
+_______________________________________________________________________________
+Release 5.0.2-1 - Matthew Flood 2006-04-08
+
+	** Changed package versioning: 
+		now using the LIBRARY_VERSION - RELEASE_VERSION
+		RELEASE_VERSION will be set to 1 for each new LIBRARY_VERSION
+		
+	** Rolled the package into binary and source RPMs
+
+_______________________________________________________________________________
+Version 3.2 - Matthew Flood 2005-06-02
+
+	** The following instance method has been added, allowing you to discover the current
+	   filepath of the config object.  The name 'getConfigFile' was chosen to pair up with the already
+		existing method - setConfigFile(const char *filepath)  
+
+			const char *getConfigFile();
+
+_______________________________________________________________________________
+Version 3.1 - Matthew Flood 2005-05-18
+
+	** The following static methods have been added, allowing you to alter the 
+		default behavior of config objects before they are created.
+	
+			static void Config::setDefaultConfigFile(const char *filepath);
+			static const char *Config::getDefaultConfigFile();
+			
+			static void Config::setDefaultCommentCharacter(char c);
+			static char Config::getDefaultCommentCharacter();
+			static void Config::setDefaultDelimiter(char c);
+			static char Config::getDefaultDelimiter();
+			static void Config::setDefaultPreserveDeleted(bool shouldPreserve);
+			static bool Config::getDefaultPreserveDeleted();
+		
+
+	** When the method [ void load(const char *filename) ] is invoked, the filename passed in
+	as a parameter is now remembered - it becomes the default filename for the instance.  
+	This means that [ bool save(void) ] will always save to the file that was load()'ed.  
+	Previously, the only way to alter the default filename for an object was to 
+	call [ void setConfigFile( const char* filepath ) ].
+
+	** setStringValue() and getStringValue() are now deprecated.
+		Use getValue() and setValue() instead.
+
+_______________________________________________________________________________
+Version 3.0 - Matthew Flood 2005-05-05
+
+	** RudeConfig became open source and is distributed under the GNU Public License.
+		Commercial licenses are available for a fee, and allow the holder
+		to use the library in commercial applications. To obtain further details, 
+		see the AUTHORS file for contact information.
+
+_______________________________________________________________________________
+
+Copyright (C) 2005 Matthew Flood
+See file AUTHORS for contact information
+
+This file is part of RudeConfig.
+
+RudeConfig 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; either version 2, or (at your option)
+any later version.
+
+RudeConfig 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 should have received a copy of the GNU General Public License
+along with RudeConfig; (see COPYING) if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
diff --git a/rudeconfig/README b/rudeconfig/README
new file mode 100644
index 0000000..e9e2e41
--- /dev/null
+++ b/rudeconfig/README
@@ -0,0 +1,66 @@
+README for RudeConfig
+See the end of file for copying conditions
+
+This file contains the following sections, please
+glance through them all before installing RudeConfig.
+
+	* Introduction
+	* Bug Reporting
+	* Copying
+
+*** INTRODUCTION ***
+
+RudeConfig is a library that allows applications 
+to (painlessly) read, modify, and create config / .ini
+files. 
+
+Documentation, discussions, and new releases are available at 
+
+http://www.rudeserver.com/
+
+See file `COPYING' for copying conditions.
+See file `INSTALL' for compilation and installation instructions.
+See file `NEWS' for a list of major changes in the current release.
+See file `THANKS' for a list of contributors.
+See file 'AUTHORS' for contact information
+
+
+*** BUG REPORTING ***
+
+Please Send bug reports to <rudeconfig@rudeserver.com>.
+A bug report should contain an adequate description of the 
+problem, your input, what you expected, what you got, 
+and why this is wrong.  Where applicable, please submit actual data
+files with your report. 
+
+Your feedback will help us to make a better and more portable package.
+Consider documentation errors as bugs, and report them as such.  If you
+develop anything pertaining to RudeConfig or have suggestions, let us know
+and share your findings by writing to <rudeconfig@rudeserver.com> or
+by visiting the discussion forum accessable from the RudeServer 
+website at http://www.rudeserver.com/
+
+
+
+*** COPYING ***
+
+Copyright (C) 2005 Matthew Flood
+See file AUTHORS for contact information
+
+This file is part of RudeConfig.
+
+RudeConfig 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; either version 2, or (at your option)
+any later version.
+
+RudeConfig 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 should have received a copy of the GNU General Public License
+along with RudeConfig; (see COPYING) if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
diff --git a/rudeconfig/THANKS b/rudeconfig/THANKS
new file mode 100644
index 0000000..cd6b8b2
--- /dev/null
+++ b/rudeconfig/THANKS
@@ -0,0 +1,10 @@
+RudeConfig THANKS file
+
+Special thanks goes out to the following individuals
+who helped to make RudeConfig a better Library.
+
+Michael Schwendt
+Ralf Corsepius
+Karen Dolan
+Ole Hansen
+
diff --git a/rudeconfig/man3/rudeconfig.3 b/rudeconfig/man3/rudeconfig.3
new file mode 100644
index 0000000..d66aa37
--- /dev/null
+++ b/rudeconfig/man3/rudeconfig.3
@@ -0,0 +1,276 @@
+.\" Process this file with 
+.\" groff -man -Tascii rudeconfig.3
+.\"
+.TH rudeconfig 3  "January 19, 2006" "Version 5.0" "User Manuals"
+.SH NAME
+rudeconfig \- read and manipulate .ini and config files
+.SH SYNOPSIS
+.B #include <rude/config.h>
+
+.BI	"rude::Config myconfig;"
+
+.PP	
+STATIC METHODS
+.nf
+.BI	"static const char *rude::version();"
+
+.BI	"static void rude::setDefaultConfigFile(const char *" "filepath" ");"
+
+.BI	"static const char *rude::getDefaultConfigFile();"
+
+.BI	"static void rude::setDefaultCommentCharacter(char " "c" ");"
+
+.BI	"static char rude::getDefaultCommentCharacter();"
+
+.BI	"static void rude::setDefaultDelimiter(char " "c" ");"
+
+.BI	"static char rude::getDefaultDelimiter();"
+
+.BI	"static void rude::setDefaultPreserveDeleted(bool " "shouldPreserve" ");"
+
+.BI	"static void rude::setDefaultPreserveDeleted(bool " "shouldPreserve" ");"
+.fi
+
+.PP	
+REDEFINING INSTANCE BEHAVIOR
+.nf
+.BI	"void setConfigFile(const char *" "filepath" ");"
+
+.BI	"const char * getConfigFile();"
+
+.BI	"void preserveDeletedData(bool " "shouldPreserve" ");"
+
+.BI	"void setCommentCharacter(char " "commentchar" ");"
+
+.BI	"void setDelimiter(char " "keyvaluedelimiter" ");"
+.fi
+
+.PP	
+LOADING AND SAVING FILES
+.nf
+.BI	"bool save();"
+
+.BI	"bool save(const char *" "filepath" ");"
+
+.BI	"void clear();"
+
+.BI	"bool load();"
+
+.BI	"bool load(const char *" "filename" ");"
+
+.BI	"const char *getError();"
+.fi
+
+.PP	
+SECTION METHODS
+.nf
+.BI	"int getNumSections() const;"
+
+.BI	"const char *getSectionNameAt(int " "index" ") const;"
+
+.BI	"bool setSection(const char *" "sectionname" ", bool shouldCreate" ");"
+
+.BI	"bool setSection(const char *" "sectionname" ");"
+
+.BI	"bool deleteSection(const char *" "sectionname" ");"
+.fi
+
+.PP	
+KEY/VALUE DISCOVERY METHODS
+.nf
+.BI	"int getNumDataMembers() const;"
+
+.BI	"const char *getDataNameAt(int " "index" ") const;"
+
+.BI	"bool exists(const char *" "name" ") const;"
+.fi
+
+.PP	
+DATA ACCESSORS
+.nf
+.BI	"bool getBoolValue(const char *" "name" ") const;"
+
+.BI	"int getIntValue(const char *" "name" ") const;"
+
+.BI	"double getDoubleValue(const char *" "name" ") const;"
+
+.BI	"const char * getValue(const char *" "name" ") const;"
+
+.BI	"const char * getStringValue(const char *" "name" ") const;"
+.fi
+
+.PP	
+DATA MUTATORS
+.nf
+.BI "void setBoolValue(const char *" "name" ", bool " "value" ");"
+
+.BI "void setIntValue(const char *" "name" ", int " "value" ");"
+
+.BI "void setDoubleValue(const char *" "name" ", double "value" ");"
+
+.BI "void setValue(const char *" "name" ", const char *" "value" ");"
+
+.BI "void setStringValue(const char *" "name" ", const char *" "value" ");"
+.fi
+
+.PP	
+KEY/VALUE DELETION
+.nf
+.BI	"bool deleteData(const char *" "name" ");"
+.fi
+
+DESTRUCTOR
+.nf
+.BI	~Config();
+.fi
+
+.SH DESCRIPTION
+
+The rudeConfig library is used to read and manipulate .ini and configuration files.
+
+.SH CONFIGURATION/.INI FILE FORMAT
+
+Configuration and .ini files have the following structure:
+
+A configuration file contains one or more "sections". 
+Each "section" contains 0 or more "key=value" pairs. 
+Sections can also contain blank lines and comments
+
+.PP
+Sections are identified by the section name surrounded by square brackets - like \fB[example section]\fP.
+The unnamed, or default section, is represented by empty square brackets - as in \fB[]\fP.
+The beginning of the configuration file, up to the first named section, is also considered part of the unnamed/default section.
+White space surrounding the section name is ignored.  Quotes can be used in section names if desired.  As such, the following section names
+are identical: 
+
+.nf
+.B [State Codes]
+.B [\ \ State Codes\ \ ]
+.B [ \&"State Codes\&" ]
+.fi
+
+.PP
+The default delimiter for key/value pairs is the equals (\fB=\fP) sign.  
+The default comment character is the hash (\fB#\fP).  
+These can be changed via the API to any character, with a few restrictions: 
+The key/value delimiter cannot be '\fB\\\fP' (escape), '\fB[\fP' (left square bracket), or any end of line character.  
+The comment character cannot be '\fB\\\fP' (escape), '\fB[\fP' (left square bracket) or '\fB"\fP' (double quote).  
+Furthermore, the key/value delimiter cannot be set to the same value as the comment character.
+
+.PP
+The key of each key/value pair within a section must be unique.
+If the same key appears more than once within a given section, all but the last key will be ignored.
+If more than one configuration file is are loaded into the same rude::Config object, duplicate key/value pairs will replace
+existing ones. 
+
+Although sections of a given name can be repeated in a physical configuration file, they are logically combined when the rude:Config object parses the file.
+If the rude:Config object is subsequently saved, then the sections will be merged- with all key/value pairs occurring one section. 
+An example of multiple sections with the same name is given here:
+
+.nf
+.B # beginning of example .ini file
+.B [State Codes]
+.B  AZ = Arizona
+.B  CO = Colorado
+.B [State Codes]
+.B  NY = New York
+.B  CA = California
+.B [State Codes]
+.B  PA = Pennsylvania
+.B  IL = Illinios
+.B #end of example .ini file
+.fi
+
+.PP
+Comments do not have to start at the beginning of a line. 
+They can appear after section declarations (on the same line) and they can appear after key=value pairs.
+
+.nf
+.B # -- first line of config file --
+.B #  this is in the default section
+.B # this is a comment
+.B # the following line is a key=value pair
+.B color=blue
+.B
+.B [contact information]
+.B # this is a new section
+.B first name=Matthew
+.B last name = Flood 	# comments are allowed after key=value pairs
+.B 
+.B []
+.B # since there is no section name, this is the default section again
+.B size=large
+.B
+.B [login info]
+.B username=scruffy
+.B password=$$324reeWrew65456
+.B 
+.B [contact information]
+.B # this section is a continuation of "contact information" section listed earlier
+.B #
+.B # the following key=value pair demonstrates using quotes for multi-line values
+.B address="111 example street
+.B apartment Z"
+.B
+.B city=boulder
+.B
+.B # -- end of config file --
+.fi
+
+
+.SH EXAMPLES
+
+Examples, how-to's and tutorials can also be found at the rudeserver.com website
+
+.B Basic Usage
+
+ #include <rude/config.h>
+
+ int main(void)
+ {
+    // Create config object
+    //
+    rude::Config config;
+
+    // load a configuration/.ini file
+    config.load("myfile.ini");
+
+
+    // read information
+    //
+    config.setSection("General Info");
+    double cost = config.getDoubleValue("Cost");
+    const char *company = config.getStringValue("Company Name");
+
+
+    // create information
+    //
+    config.setSection("new section");
+    config.setStringValue("animal type", "giraffe");
+    config.setBoolValue("mammal", true);
+
+    // save changes
+    //
+    config.save();
+    return 0;
+ }
+	
+.SH SEE ALSO
+.BR rudecgiparser(3),
+.BR rudedatabase(3),
+.BR rudesocket(3),
+.BR rudesession(3)
+
+.SH REPORTING PROBLEMS
+
+Before reporting a problem, please check the rudeserver.com web site to verify that you have the latest version of rudeconfig; otherwise, obtain the latest version and see if the problem still exists.  Please read the  FAQ at:
+
+              http://www.rudeserver.com/
+
+before asking for help.  Send questions and/or comments to  matt@rudeserver.com
+
+.SH AUTHORS
+Copyright (C) 2000 Matthew Flood (matt@rudeserver.com)
+
+This  software is provided "as-is," without any express or implied warranty.  In no event will the authors be held liable for any damages arising from the use of this software.  See the distribution directory with respect  to  requirements  governing  redistribution. Thanks to all the people who reported problems and suggested various improvements in rudeconfig; who are too numerous to cite here.
+
diff --git a/rudeconfig/src/AbstractData.cpp b/rudeconfig/src/AbstractData.cpp
new file mode 100644
index 0000000..051d326
--- /dev/null
+++ b/rudeconfig/src/AbstractData.cpp
@@ -0,0 +1,43 @@
+// AbstractData.cc
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "AbstractData.h"
+
+
+namespace rude{
+namespace config{
+
+AbstractData::AbstractData()
+{
+
+}
+
+AbstractData::~AbstractData()
+{
+
+}
+
+}} // end namespaces
+
diff --git a/rudeconfig/src/AbstractData.h b/rudeconfig/src/AbstractData.h
new file mode 100644
index 0000000..14d13b5
--- /dev/null
+++ b/rudeconfig/src/AbstractData.h
@@ -0,0 +1,49 @@
+// AbstractData.h
+// Acts as the base Element that accepts visitors in the Visitor design pattern
+//
+// This file is part of RudeConfig.
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#ifndef INCLUDED_AbstractData_H
+#define INCLUDED_AbstractData_H
+
+namespace rude{
+namespace config{
+
+class AbstractWriter;
+
+class AbstractData{
+
+protected:
+	AbstractData();
+
+public:
+	virtual ~AbstractData();
+	virtual void acceptWriter(AbstractWriter& writer) const = 0;
+
+
+};
+
+
+}} // end namespaces
+
+#endif
+
diff --git a/rudeconfig/src/AbstractOrganiser.cpp b/rudeconfig/src/AbstractOrganiser.cpp
new file mode 100644
index 0000000..e9aaf17
--- /dev/null
+++ b/rudeconfig/src/AbstractOrganiser.cpp
@@ -0,0 +1,42 @@
+// AbstractOrganiser.cc
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "AbstractOrganiser.h"
+
+namespace rude{
+namespace config{
+
+	AbstractOrganiser::AbstractOrganiser()
+	{
+	}
+
+
+	AbstractOrganiser::~AbstractOrganiser()
+	{
+	}
+
+
+}} // end namespaces
+
diff --git a/rudeconfig/src/AbstractOrganiser.h b/rudeconfig/src/AbstractOrganiser.h
new file mode 100644
index 0000000..2a50f38
--- /dev/null
+++ b/rudeconfig/src/AbstractOrganiser.h
@@ -0,0 +1,57 @@
+// AbstractOrganiser.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#ifndef INCLUDED_AbstractOrganiser_h
+#define INCLUDED_AbstractOrganiser_h
+
+namespace rude{
+namespace config{
+
+class AbstractOrganiser
+{
+
+public:
+
+	AbstractOrganiser();
+	virtual ~AbstractOrganiser();
+
+	virtual void foundSection(const char *sectionName, const char *comment) = 0;
+	virtual void foundComment(const char *comment) = 0;
+	virtual void foundWhiteSpace(const char *whitespace) = 0;
+	virtual void foundData(const char *key, const char *value, const char *comment) = 0;
+	/* remedius
+	 * two more parameters: communication type (commType) and
+	 * processing method (procMethod) were added.
+	 */
+	virtual void foundSourceDest(const char *srcApp, const char *srcObj,
+			const char *destApp, const char *destObj,
+			const char *width, const char *commType, const char*procMethod,
+			const char *comment) = 0;
+
+
+};
+
+}} // end namespaces
+
+#endif
+
diff --git a/rudeconfig/src/AbstractParser.cpp b/rudeconfig/src/AbstractParser.cpp
new file mode 100644
index 0000000..b8408d2
--- /dev/null
+++ b/rudeconfig/src/AbstractParser.cpp
@@ -0,0 +1,78 @@
+// AbstractParser.cc
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "AbstractParser.h"
+
+using namespace rude::config;
+using namespace std;
+
+namespace rude{
+namespace config{
+
+
+AbstractParser::AbstractParser()
+{
+	d_error = "";
+	d_errorcode = "";
+	d_commentchar = '#';
+	d_delimiter = '=';
+}
+
+AbstractParser::~AbstractParser()
+{
+
+}
+
+void AbstractParser::setCommentCharacter(char c)
+{
+	d_commentchar = c;
+}
+
+void AbstractParser::setDelimiter(char c)
+{
+	d_delimiter = c;
+}
+
+const char *AbstractParser::getErrorCode() const
+{
+	return d_errorcode.c_str();
+}
+
+const char *AbstractParser::getError() const
+{
+	return d_error.c_str();
+}
+
+void AbstractParser::setError(const char *code, const char *message)
+{
+	d_errorcode = code ? code : "";
+	d_error = message ? message : "";
+}
+
+}} // end namespaces
+
+
+
+
diff --git a/rudeconfig/src/AbstractParser.h b/rudeconfig/src/AbstractParser.h
new file mode 100644
index 0000000..40e8eae
--- /dev/null
+++ b/rudeconfig/src/AbstractParser.h
@@ -0,0 +1,73 @@
+// AbstractParser.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#ifndef INPUT_AbstractParser_h
+#define INPUT_AbstractParser_h
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+namespace rude{
+namespace config{
+
+class ConfigInput;
+class AbstractOrganiser;
+
+
+class AbstractParser
+{
+	std::string d_error;
+	std::string d_errorcode;
+	
+protected:
+
+	char d_commentchar;
+	char d_delimiter;
+	void setError(const char *code, const char *message);
+
+public:
+
+	AbstractParser();
+	virtual ~AbstractParser();
+
+	void setCommentCharacter(char c);
+	void setDelimiter(char c);
+
+	const char *getErrorCode() const;
+	const char *getError() const;
+	
+	virtual bool parse(std::istream& inputstream, AbstractOrganiser& organiser) = 0;
+
+};
+
+}} // end namespaces
+
+#endif
+
diff --git a/rudeconfig/src/AbstractWriter.cpp b/rudeconfig/src/AbstractWriter.cpp
new file mode 100644
index 0000000..f710ffe
--- /dev/null
+++ b/rudeconfig/src/AbstractWriter.cpp
@@ -0,0 +1,83 @@
+// AbstractWriter.cc
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "AbstractWriter.h"
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+namespace rude{
+namespace config{
+
+AbstractWriter::AbstractWriter()
+{
+	d_commentchar = '#';
+	d_delimiter = '=';
+	d_preservedeleted = false;
+	d_preservecomments = true;
+	d_preservewhitespace = true;
+	d_outputstream = &std::cout;
+}
+
+AbstractWriter::~AbstractWriter()
+{
+
+}
+
+
+void AbstractWriter::setOutputStream( std::ostream& stream)
+{
+	d_outputstream = &stream;
+}
+
+void AbstractWriter::setCommentChar(char c)
+{
+	d_commentchar = c;
+}
+
+void AbstractWriter::setDelimiter(char c)
+{
+	d_delimiter = c;
+}
+
+void AbstractWriter::preserveDeleted(bool doit)
+{
+	d_preservedeleted = doit;
+}
+
+void AbstractWriter::preserveComments(bool doit)
+{
+	d_preservecomments = doit;
+}
+
+void AbstractWriter::preserveWhiteSpace(bool doit)
+{
+	d_preservewhitespace = doit;
+}
+
+}} // end namespaces
+
diff --git a/rudeconfig/src/AbstractWriter.h b/rudeconfig/src/AbstractWriter.h
new file mode 100644
index 0000000..71ebdb7
--- /dev/null
+++ b/rudeconfig/src/AbstractWriter.h
@@ -0,0 +1,79 @@
+// AbstractWriter.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#ifndef INCLUDED_AbstractWriter_H
+#define INCLUDED_AbstractWriter_H
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+namespace rude{
+namespace config{
+
+class File;
+class Section;
+class KeyValue;
+class Comment;
+class WhiteSpace;
+
+class AbstractWriter{
+
+
+protected:
+
+	char d_commentchar;
+	char d_delimiter;
+	bool d_preservedeleted;
+	bool d_preservecomments;
+	bool d_preservewhitespace;
+	
+	std::ostream *d_outputstream;
+
+	AbstractWriter();
+
+public:
+
+	virtual void visitFile(const File& configfile) const = 0;
+	virtual void visitSection(const Section& configsection) const = 0;
+	virtual void visitKeyValue(const KeyValue& dataline) const = 0;
+	virtual void visitComment(const Comment& comment) const = 0;
+	virtual void visitWhiteSpace(const WhiteSpace& whitespace) const = 0;
+
+	void setOutputStream( std::ostream& stream);
+	void setCommentChar(char);
+	void setDelimiter(char);
+	void preserveDeleted(bool doit);
+	void preserveComments(bool doit);
+	void preserveWhiteSpace(bool doit);
+
+	virtual ~AbstractWriter();
+
+};
+
+
+}} // end namespaces
+
+#endif
+
diff --git a/rudeconfig/src/Base64Encoder.cpp b/rudeconfig/src/Base64Encoder.cpp
new file mode 100644
index 0000000..6c9c111
--- /dev/null
+++ b/rudeconfig/src/Base64Encoder.cpp
@@ -0,0 +1,331 @@
+// Base64Encoder.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "Base64Encoder.h"
+
+#ifndef INCLUDED_CSTRING
+#include <string.h>
+#define INCLUDED_CSTRING
+#endif
+
+namespace rude{
+namespace config{
+
+// translates a 6 bit char into a base-64 character
+//
+inline char Base64Encoder::c_encode(char uc)
+{
+	if (uc < 26)
+	{
+		return 'A'+uc;
+	}
+	if (uc < 52)
+	{
+		return 'a'+(uc-26);
+	}
+    if (uc < 62)
+	{
+		return '0'+(uc-52);
+	}
+	if (uc == 62)
+	{
+		return '+';
+	}
+	return '/';
+}
+
+// translates one base-64 character into a six-bit pattern
+//
+inline unsigned char Base64Encoder::c_decode(char c)
+{
+      if (c >= 'A' && c <= 'Z')
+      {
+            return c - 'A';
+      }
+      if (c >= 'a' && c <= 'z')
+      {
+            return c - 'a' + 26;
+      }
+      if (c >= '0' && c <= '9')
+      {
+            return c - '0' + 52;
+      }
+      if (c == '+')
+      {
+            return 62;
+      };
+      return 63;
+}
+
+
+char * Base64Encoder::encode(const char *data, int datalength, int &outlength)
+{
+      
+	
+      int linelength=0;
+      outlength=0;
+ 
+      if (data == (char*) 0 || datalength == 0)
+      {
+            return (char*) 0;
+      };
+
+		char *retval=new char[datalength * 2];
+		const char *crlf="\n";
+		int crlflength=strlen(crlf);
+		int maxlinelength=76;
+		
+      for (int i=0; i<datalength; i+=3)
+      {
+				unsigned char by1, by2, by3, by4, by5, by6, by7;
+            by1 = data[i];
+				
+            if (i+1 < datalength)
+            {
+                  by2 = data[i+1];
+            }
+				else
+				{
+	            by2=0;
+				}
+				
+            if (i+2 < datalength)
+            {
+                  by3 = data[i+2];
+            }
+				else
+				{
+					by3=0;
+				}
+
+            by4 = by1>>2;
+            by5 = ((by1 & 0x3)<<4)|( by2>>4 );
+            by6 = ((by2 & 0xf)<<2)|( by3>>6 );
+            by7 = by3 & 0x3f;
+
+
+
+            retval[outlength++] = c_encode(by4);
+            linelength++;
+				
+            retval[outlength++] = c_encode(by5);
+            linelength++;
+ 
+            if (i+1 < datalength)
+            {
+                  retval[outlength++]= c_encode(by6);
+                  linelength++;
+            }
+            else
+            {
+                  retval[outlength++]= '=';
+                  linelength++;
+            }
+
+            if (i+2<datalength)
+            {
+                  retval[outlength++]= c_encode(by7);
+                  linelength++;
+            }
+            else
+            {
+                  retval[outlength++]= '=';
+                  linelength++;
+            };
+
+				// only set linelength if maxlinelength > 0
+				//
+            if (maxlinelength != 0 && linelength >= maxlinelength)
+            {
+						for(int y=0; y< crlflength; y++)
+						{
+							retval[outlength++]= crlf[y];
+						}
+						
+						// we just created a line - reset current linelength
+						//
+                  linelength=0;
+            }
+      };
+      retval[outlength]=(char) NULL;
+      return retval;
+}
+
+
+char * Base64Encoder::decode(const char *data, int datalength, int &outlength)
+{
+		// Error if incoming data is NULL
+		// Error if nothing to decode
+		//
+		if(data == (char *) 0 || datalength == 0)
+		{
+			return (char*) 0;
+		}
+
+	
+      outlength=0;
+
+		// rawlength is the length of the encoded data excluding
+		// any non-base64 characters
+		//
+      int rawlength=0;
+
+
+		// create return buffer
+		//
+		char *outbuffer=new char[datalength];
+
+      // copy all base64 characters into outbuffer,
+      // in other words, strip away CRLF's and non-b64 characters...
+		//
+      for (int j=0;j < datalength; j++)
+      {
+            if (IsBase64(data[j]))
+            {
+                  outbuffer[rawlength++]= data[j];
+            }
+      }
+
+		// there's no base64 characters to decode
+		//
+      if (rawlength == 0 || datalength == 0)
+      {
+				delete [] outbuffer;
+            return (char*) NULL;
+      }
+
+ 
+
+      for (int i=0; i<rawlength; i+=4)
+
+      {
+
+            
+
+            char c1 = outbuffer[i];
+				char c2='A',c3='A',c4='A';
+
+            if (i+1 < rawlength)
+
+            {
+
+                  c2 = outbuffer[i+1];
+
+            };
+
+            if (i+2 < rawlength)
+
+            {
+
+                  c3 = outbuffer[i+2];
+
+            };
+
+            if (i+3 < rawlength)
+
+            {
+
+                  c4 = outbuffer[i+3];
+
+            };
+
+ 
+
+            unsigned char by1,by2,by3,by4;
+
+            by1 = c_decode(c1);
+
+            by2 = c_decode(c2);
+
+            by3 = c_decode(c3);
+
+            by4 = c_decode(c4);
+
+ 
+
+            outbuffer[outlength]=( (by1<<2)|(by2>>4) );
+            outlength++;
+ 
+
+            if (c3 != '=')
+
+            {
+
+                  outbuffer[outlength]=( ((by2&0xf)<<4)|(by3>>2) );
+                  outlength++;
+            }
+
+ 
+
+            if (c4 != '=')
+
+            {
+
+                  outbuffer[outlength]=( ((by3&0x3)<<6)|by4 );
+                  outlength++;
+            };
+
+      };
+		// NULL terminate decoded data
+		// in case caller ignores outlength
+		// for text data
+		//
+      outbuffer[outlength]=(char) 0;
+      return outbuffer;
+}
+
+//The last helper function returns true is a character is a valid
+//base-64 character and false otherwise.
+inline bool Base64Encoder::IsBase64(char c)
+{
+      if (c >= 'A' && c <= 'Z')
+      {
+            return true;
+      }
+      if (c >= 'a' && c <= 'z')
+      {
+            return true;
+      }
+      if (c >= '0' && c <= '9')
+      {
+            return true;
+      }
+      if (c == '+')
+      {
+            return true;
+      };
+      if (c == '/')
+      {
+            return true;
+      };
+      if (c == '=')
+      {
+            return true;
+      };
+      return false;
+}
+
+}}
+
diff --git a/rudeconfig/src/Base64Encoder.h b/rudeconfig/src/Base64Encoder.h
new file mode 100644
index 0000000..9ae5662
--- /dev/null
+++ b/rudeconfig/src/Base64Encoder.h
@@ -0,0 +1,64 @@
+// Base64Encoder.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#ifndef INCLUDED_BASE64ENCODER_H
+#define INCLUDED_BASE64ENCODER_H
+
+
+namespace rude{
+namespace config{
+
+class Base64Encoder{
+
+private:
+      static char c_encode(char uc);
+      static unsigned char c_decode(char c);
+      static bool IsBase64(char c);
+
+public:
+
+		// datalength does not need to include the NULL terminator for strings
+		//
+		// a NULL terminator is appended to result to make it string friendly
+		// but outlength does not include the
+		// appended NULL terminator in length calculation
+		//
+		// CALLER RESPONSIBLE FOR DELETING RETURNED char * if it is not NULL.
+		//
+		static char * encode(const char *data, int datalength, int &outlength);
+
+
+		// datalength does not need to include the NULL terminator for strings
+		// NULL Terminator is appended to result, but outlength does not include the
+		// appended NULL terminator in length calculation
+		//
+		// CALLER RESPONSIBLE FOR DELETING RETURNED char * if it is not NULL.
+		//
+		static char * decode(const char *data, int datalength, int &outlength);
+
+};
+}}
+
+#endif
+
+
diff --git a/rudeconfig/src/Comment.cpp b/rudeconfig/src/Comment.cpp
new file mode 100644
index 0000000..a9b93a8
--- /dev/null
+++ b/rudeconfig/src/Comment.cpp
@@ -0,0 +1,58 @@
+// Comment.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#include "../config.h"
+
+#include "Comment.h"
+
+#ifndef INCLUDED_AbstractWriter_H
+#include "AbstractWriter.h"
+#endif
+
+#ifndef INCLUDED_CSTDIO
+#include <cstdio>
+#define INCLUDED_CSTDIO
+#endif
+
+using namespace std;
+namespace rude{
+namespace config{
+
+Comment::Comment(const char *comment)
+{
+	d_comment = comment ? comment : "";
+}
+
+void Comment::acceptWriter(AbstractWriter& writer) const
+{
+	writer.visitComment(*this);
+}
+
+const char *Comment::getComment() const
+{
+	return d_comment.c_str();
+}
+
+}} // end namespace rude::config
+
diff --git a/rudeconfig/src/Comment.h b/rudeconfig/src/Comment.h
new file mode 100644
index 0000000..ac21bd1
--- /dev/null
+++ b/rudeconfig/src/Comment.h
@@ -0,0 +1,57 @@
+// Comment.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#ifndef INCLUDED_Comment_H
+#define INCLUDED_Comment_H
+
+#ifndef INCLUDED_DataLine_H
+#include "DataLine.h"
+#endif
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+namespace rude{
+namespace config{
+
+class Comment: public DataLine{
+
+	std::string d_comment;
+
+public:
+
+	Comment(const char *comment);
+	
+	void acceptWriter(AbstractWriter& writer) const;
+
+	const char *getComment() const;
+	
+};
+
+}} // end namespace rude::config
+
+#endif
+
diff --git a/rudeconfig/src/ConfigImpl.cpp b/rudeconfig/src/ConfigImpl.cpp
new file mode 100644
index 0000000..1787b34
--- /dev/null
+++ b/rudeconfig/src/ConfigImpl.cpp
@@ -0,0 +1,616 @@
+// configimpl.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+#include "../config.h"
+
+#include "ConfigImpl.h"
+
+#ifndef INCLUDED_Section_H
+#include "Section.h"
+#endif
+
+#ifndef INCLUDED_File_H
+#include "File.h"
+#endif
+
+#ifndef INCLUDED_Writer_H
+#include "Writer.h"
+#endif
+
+#ifndef INPUT_RealOrganiser_h
+#include "RealOrganiser.h"
+#endif
+
+#ifndef INPUT_ParserJuly2004_h
+#include "ParserJuly2004.h"
+#endif
+
+#ifndef INCLUDED_BASE64ENCODER_H
+#include "Base64Encoder.h"
+#endif
+
+
+#ifndef INCLUDED_CSTDIO
+#include <cstdio>
+#define INCLUDED_CSTDIO
+#endif
+
+#ifndef INCLUDED_CSTDLIB
+#include <cstdlib>
+#define INCLUDED_CSTDLIB
+#endif
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+#ifndef INCLUDED_FSTREAM
+#include <fstream>
+#define INCLUDED_FSTREAM
+#endif
+
+#include <cstring>
+
+using namespace std;
+
+namespace rude{
+namespace config{
+
+// STATIC DATA
+//
+
+std::string ConfigImpl::s_defaultConfigFile = "default.ini";
+char ConfigImpl::s_defaultCommentChar = '#';
+char ConfigImpl::s_defaultDelimiter = '=';
+bool ConfigImpl::s_defaultPreserveDeleted = false;
+bool ConfigImpl::s_defaultAllowDuplicate = false;
+bool ConfigImpl::s_defaultIgnoreCase = false;
+std::string ConfigImpl::s_returnValue="";
+
+
+//////////////////////////////////////
+// STATIC METHODS
+//////////////////////////////////////
+
+const char *ConfigImpl::version()
+{
+	return "0";
+}
+	
+void ConfigImpl::setDefaultConfigFile(const char *filepath)
+{
+	s_defaultConfigFile = filepath ? filepath : "default.ini";
+}
+const char *ConfigImpl::getDefaultConfigFile()
+{
+	return s_defaultConfigFile.c_str();
+}
+
+
+void ConfigImpl::setDefaultCommentCharacter(char c)
+{
+	s_defaultCommentChar = c;
+}
+
+char ConfigImpl::getDefaultCommentCharacter()
+{
+	return s_defaultCommentChar;
+}
+
+
+void ConfigImpl::setDefaultDelimiter(char c)
+{
+	s_defaultDelimiter = c;
+}
+
+char ConfigImpl::getDefaultDelimiter()
+{
+	return s_defaultDelimiter;
+}
+
+void ConfigImpl::setDefaultPreserveDeleted(bool shouldPreserve)
+{
+	s_defaultPreserveDeleted = shouldPreserve;
+}
+
+bool ConfigImpl::getDefaultPreserveDeleted()
+{
+	return s_defaultPreserveDeleted;
+}
+
+
+void ConfigImpl::setDefaultIgnoreCase(bool shouldIgnore)
+{
+	s_defaultIgnoreCase = shouldIgnore;
+}
+
+void ConfigImpl::setDefaultAllowDuplicateKeys(bool shouldAllow)
+{
+	s_defaultAllowDuplicate = shouldAllow;
+}
+
+// STATIC DATA CONVERSION
+//
+bool ConfigImpl::stringToBool(const char *value)
+{
+	if(value)
+	{
+		// Values that mean true:
+		// yes, on, true, 1
+		// [yY]*, [oO][nN]*, O*, [Tt]*, 1
+		// Values that mean false:
+		// no, off, false, 0
+
+		switch(value[0])
+		{
+			case 't':
+				return true;
+			case 'T':
+				return true;
+			case 'y':
+				return true;
+			case 'Y':
+				return true;
+			case '1':
+				return true;
+			case 'o':
+				if(value[1] == 'n' || value[1] == 'N')
+				{
+					// since value[0] was not null, we can rest assured that there is a value[1] -
+					// it is at least the null string terminator!
+					return true;
+				}
+				break;
+			case 'O':
+				if(value[1] == 'n' || value[1] == 'N')
+				{
+					return true;
+				}
+				break;
+			default:
+				return false;
+		}
+	}
+	return false;
+}
+
+const char *ConfigImpl::boolToString(bool value)
+{
+	return (value ? "true" : "false");
+}
+
+int ConfigImpl::stringToInt(const char *string)
+{
+	if(string)
+	{
+		return atoi(string);
+	}
+	return 0;
+}
+
+const char *ConfigImpl::intToString(int value)
+{
+	char myint[25];
+	sprintf(myint, "%i", value);
+	s_returnValue = myint;
+	return s_returnValue.c_str();
+}
+
+double ConfigImpl::stringToDouble(const char *string)
+{
+	if(string)
+	{
+		return atof(string);
+	}
+	return 0;
+}
+
+const char *ConfigImpl::doubleToString(double value)
+{
+	char mydouble[25];
+	sprintf(mydouble, "%g", value);
+	s_returnValue = mydouble;
+	return s_returnValue.c_str();
+}
+
+char * ConfigImpl::stringToBinary(const char *value, int &outlength)
+{
+	// Base64Encoder USAGE:
+	// static char * decode(const char *data, int datalength, int &outlength);
+
+	if(value)
+	{
+		int datalength=strlen(value);
+		return Base64Encoder::decode(value, datalength, outlength);
+	}
+	outlength=0;
+	return 0;
+}
+
+const char *ConfigImpl::binaryToString(const char *value, int length)
+{
+	
+	// Base64Encoder USAGE:
+	// static char * encode(const char *data, int datalength, int &outlength);
+
+	if(value)
+	{
+		int outlength;
+		s_returnValue = Base64Encoder::encode(value, length, outlength);
+	}
+	else
+	{
+		s_returnValue = "";
+	}
+	return s_returnValue.c_str();
+}
+
+
+//////////////////////////////////////
+// INSTANCE METHODS
+//////////////////////////////////////
+
+
+	///////////////////////////
+	// CONSTRUCTOR & DESTRUCTOR
+	///////////////////////////
+
+ConfigImpl::ConfigImpl()
+{
+	d_file = new File();
+
+	// Create the appropriate Objects here, 
+	// all other methods interact with
+	// the base class interfaces
+	// 
+	d_writer = new Writer();
+	
+	d_parser = new ParserJuly2004();
+
+	d_error="";
+	d_errorcode="";
+	
+	d_commentcharacter = s_defaultCommentChar;
+	d_delimiter = s_defaultDelimiter;
+	d_configfile = s_defaultConfigFile;
+	d_preserveDeleted = s_defaultPreserveDeleted;
+	d_allowDuplicate = s_defaultAllowDuplicate;
+	d_ignoreCase = s_defaultIgnoreCase;
+
+
+} 
+
+ConfigImpl::~ConfigImpl()
+{
+	delete d_writer;
+	delete d_parser;
+	delete d_file;
+}
+
+	////////////
+	// STATUS
+	////////////
+
+void ConfigImpl::setError(const char *errorcode, const char *errorstring)
+{
+	d_errorcode = errorcode ? errorcode : "";
+	d_error = errorstring ? errorstring : "";
+}
+
+const char *ConfigImpl::getError() const
+{
+	return d_error.c_str();
+}
+
+const char *ConfigImpl::getErrorCode() const
+{
+	return d_errorcode.c_str();
+}
+
+	//////////////////////
+	// INSTANCE BEHAVIOR
+	//////////////////////
+
+void ConfigImpl::setConfigFile(const char *filepath)
+{
+	d_configfile = filepath ? filepath : s_defaultConfigFile.c_str();
+}
+const char * ConfigImpl::getConfigFile()
+{
+	return d_configfile.c_str();
+}
+
+void ConfigImpl::setCommentCharacter(char c)
+{
+	d_commentcharacter = c;
+}
+
+void ConfigImpl::setDelimiter(char c)
+{
+	d_delimiter = c;
+}
+
+void ConfigImpl::preserveDeletedData(bool shouldPreserve)
+{
+	d_preserveDeleted = shouldPreserve;
+}
+
+void ConfigImpl::ignoreCase(bool shouldIgnore)
+{
+	d_ignoreCase = shouldIgnore;
+}
+
+void ConfigImpl::allowDuplicateKeys(bool shouldAllow)
+{
+	d_allowDuplicate = shouldAllow;
+}
+
+	//////////////////////////////
+	// LOADING & SAVING & CLEARING
+	//////////////////////////////
+
+bool ConfigImpl::load()
+{
+	// forward to load(filepath)
+	//
+	return load(d_configfile.c_str());
+}
+
+bool ConfigImpl::load(const char *filepath)
+{
+
+	if(filepath && filepath[0])
+	{
+		d_configfile=filepath;
+		std::ifstream infile(filepath);
+
+		if(infile)
+		{
+			// forward to load(std::istream&)
+			bool retval = load(infile);
+			infile.close();
+			return retval;
+		}
+		else
+		{
+			setError("2001", "Error opening config file for reading");
+			return false;
+		}
+	}
+	else
+	{
+		return load(std::cin);
+	}
+}
+
+bool ConfigImpl::load(std::istream& inputstream)
+{	
+	d_parser->setCommentCharacter(d_commentcharacter);
+	
+	d_parser->setDelimiter(d_delimiter);
+
+	RealOrganiser organiser(d_file);
+	
+	if(d_parser->parse(inputstream, organiser))
+	{
+		setSection("");
+		return true;
+	}
+	else
+	{	
+		setSection("");
+		setError(d_parser->getErrorCode(), d_parser->getError());
+		return false;
+	}
+}
+	
+bool ConfigImpl::save()
+{
+	// forward to save(filepath)
+	//
+	return save(d_configfile.c_str());
+}
+
+bool ConfigImpl::save(const char *filepath)
+{
+	if(filepath && filepath[0] != 0)
+	{
+		ofstream outstream(filepath);
+		if(outstream)
+		{
+			// forward to save(std::ostream&)
+			//
+			bool retval = save(outstream);
+			outstream.close();
+			return retval;
+		}
+		else
+		{
+			setError("2002", "Error opening config file for writing");
+			return false;
+		}
+	}
+	else
+	{
+		return save(std::cout);
+	}
+}
+
+bool ConfigImpl::save(std::ostream& outstream)
+{
+	d_writer->setOutputStream(outstream);
+	d_writer->setCommentChar(d_commentcharacter);
+	d_writer->setDelimiter(d_delimiter);
+	d_writer->preserveDeleted(d_preserveDeleted);
+
+	d_file->acceptWriter(*d_writer);
+
+	return true;
+}
+
+void ConfigImpl::clear()
+{
+	d_file->clear();
+}
+
+
+	//////////////////
+	// SECTION METHODS
+	//////////////////
+
+
+int ConfigImpl::getNumSections() const
+{
+	return d_file->getNumSections();
+}
+
+const char *ConfigImpl::getSectionNameAt(int index) const
+{
+	return d_file->getSectionNameAt(index);
+}
+
+bool ConfigImpl::setSection(const char *sectionname, bool shouldCreate)
+{
+	return d_file->setSection(sectionname, shouldCreate);
+}
+
+bool ConfigImpl::setSection(const char *sectionname)
+{
+	return d_file->setSection(sectionname, true);
+}
+
+bool ConfigImpl::deleteSection(const char *sectionname)
+{
+	return d_file->deleteSection(sectionname);
+}
+
+	////////////////
+	// DATA METHODS
+	////////////////
+
+int ConfigImpl::getNumSourceDestMembers() const
+{
+  return d_file->getNumSourceDestMembers();
+}
+
+const char *ConfigImpl::getSrcAppAt(int index) const
+{
+  return d_file->getSrcAppAt(index);
+}
+
+const char *ConfigImpl::getDestAppAt(int index) const
+{
+  return d_file->getDestAppAt(index);
+}
+
+const char *ConfigImpl::getSrcObjAt(int index) const
+{
+  return d_file->getSrcObjAt(index);
+}
+
+const char *ConfigImpl::getDestObjAt(int index) const
+{
+  return d_file->getDestObjAt(index);
+}
+
+const char *ConfigImpl::getWidthAt(int index) const
+{
+  return d_file->getWidthAt(index);
+}
+const char *ConfigImpl::getCommTypeAt(int index) const
+{
+	return d_file->getCommTypeAt(index);
+}
+const char *ConfigImpl::getProcMethodAt(int index) const
+{
+	return d_file->getProcMethodAt(index);
+}
+
+int ConfigImpl::getNumDataMembers() const
+{
+		return d_file->getNumDataMembers();
+}
+
+const char *ConfigImpl::getDataNameAt(int index) const
+{
+		return d_file->getDataNameAt(index);
+}
+
+const char *ConfigImpl::getDataValueAt(int index) const
+{
+		return d_file->getDataValueAt(index);
+}
+
+bool ConfigImpl::exists(const char *name) const
+{
+		return d_file->exists(name);
+}
+	
+const char * ConfigImpl::getStringValue(const char *name) const
+{
+	return d_file->getStringValue(name);
+}
+
+void ConfigImpl::setStringValue(const char *name, const char *value)
+{
+	d_file->setStringValue(name, value);
+}
+
+bool ConfigImpl::deleteData(const char *name)
+{
+	return d_file->deleteData(name);
+}
+
+	///////////////////////////////
+	// Working with Duplicate Keys
+	// NOT IMPLEMENTED YET
+	///////////////////////////////
+
+int ConfigImpl::getNumDataMembers(const char *key) const
+{
+	if(exists(key))
+	{
+		return 1;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+const char * ConfigImpl::getStringValue(const char *name, int index) const
+{
+	return d_file->getStringValue(name);
+}
+
+void ConfigImpl::addStringValue(const char *name, const char *value)
+{
+	d_file->setStringValue(name, value);
+}
+
+bool ConfigImpl::deleteData(const char *name, int index)
+{
+	return d_file->deleteData(name);
+}
+
+}}// end namespace rude::config
diff --git a/rudeconfig/src/ConfigImpl.h b/rudeconfig/src/ConfigImpl.h
new file mode 100644
index 0000000..a4cbc60
--- /dev/null
+++ b/rudeconfig/src/ConfigImpl.h
@@ -0,0 +1,199 @@
+// ConfigImpl.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#ifndef INCLUDED_RUDE_CONFIGIMPL_H
+#define INCLUDED_RUDE_CONFIGIMPL_H
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+namespace rude{
+namespace config{
+
+class Section;
+class File;
+class AbstractWriter;
+class AbstractParser;
+class AbstractOrganiser;
+
+class ConfigImpl{
+
+	static std::string s_defaultConfigFile;
+	static char s_defaultCommentChar;
+	static char s_defaultDelimiter;
+	static bool s_defaultPreserveDeleted;
+	static bool s_defaultAllowDuplicate;
+	static bool s_defaultIgnoreCase;
+	static std::string s_returnValue;
+
+	AbstractWriter *d_writer;
+	AbstractOrganiser *d_organiser;
+	AbstractParser *d_parser;
+	
+	File *d_file;
+	std::string d_error;
+	std::string d_errorcode;
+
+	std::string d_configfile;
+	char d_commentcharacter;
+	char d_delimiter;
+	bool d_preserveDeleted;
+	bool d_allowDuplicate;
+	bool d_ignoreCase;
+
+protected:
+
+	void setError(const char *errorcode, const char *errorstring);
+
+public:
+
+	//////////////////////////////////////
+	// STATIC METHODS
+	//////////////////////////////////////
+	static const char *version();
+	
+	// DEFAULT BEHAVIOR
+	//
+	static void setDefaultConfigFile(const char *filepath);
+	static const char *getDefaultConfigFile();
+			
+	static void setDefaultCommentCharacter(char c);
+	static char getDefaultCommentCharacter();
+
+	static void setDefaultDelimiter(char c);
+	static char getDefaultDelimiter();
+	
+	static void setDefaultPreserveDeleted(bool shouldPreserve);
+	static bool getDefaultPreserveDeleted();
+
+	// The internals are on the drawing board!!
+	//
+	static void setDefaultIgnoreCase(bool shouldIgnore);
+	static void setDefaultAllowDuplicateKeys(bool shouldAllow);
+
+			
+	// DATA CONVERSION
+	//
+	static bool stringToBool(const char *string);
+	static const char *boolToString(bool value);
+	static int stringToInt(const char *string);
+	static const char *intToString(int value);
+	static double stringToDouble(const char *string);
+	static const char *doubleToString(double value);
+	static char * stringToBinary(const char *value, int &outlength);
+	static const char *binaryToString(const char *value, int length); 
+
+
+	//////////////////////////////////////
+	// INSTANCE METHODS
+	//////////////////////////////////////
+
+	// CONSTRUCTOR & DESTRUCTOR
+	//
+	ConfigImpl();
+	~ConfigImpl();
+
+	// STATUS
+	//
+	const char *getError() const;
+	const char *getErrorCode() const;
+
+	// INSTANCE BEHAVIOR
+	//
+	void setConfigFile(const char *filepath);
+	const char *getConfigFile();
+	void setCommentCharacter(char c);
+	void setDelimiter(char c);
+	void preserveDeletedData(bool shouldPreserve);
+	void ignoreCase(bool shouldIgnore);
+	void allowDuplicateKeys(bool shouldAllow);
+
+	// LOADING & SAVING & CLEARING
+	//	
+	bool load();
+	bool load(const char *filepath);
+	bool load(std::istream&);
+	
+	bool save();
+	bool save(const char *filepath);
+	bool save(std::ostream&);
+
+	void clear();
+
+
+	// SECTION METHODS
+	//
+	int getNumSections() const;
+	const char *getSectionNameAt(int index) const;
+	bool setSection(const char *sectionname, bool shouldCreate);
+	bool setSection(const char *sectionname);
+	bool deleteSection(const char *sectionname);
+
+
+	// DATA METHODS
+	//
+
+        int getNumSourceDestMembers() const;
+        const char *getSrcAppAt(int index) const;
+        const char *getDestAppAt(int index) const;
+        const char *getSrcObjAt(int index) const;
+        const char *getDestObjAt(int index) const;
+        const char *getWidthAt(int index) const;
+        /* remedius
+         *
+         */
+        const char *getCommTypeAt(int index) const;
+        /* remedius
+         *
+         */
+        const char *getProcMethodAt(int index) const;
+
+	int getNumDataMembers() const;
+	const char *getDataNameAt(int index) const;
+	const char *getDataValueAt(int index) const;
+	bool exists(const char *name) const;
+	
+	const char * getStringValue(const char *name) const;
+	void setStringValue(const char *name, const char *value);
+	bool deleteData(const char *name);
+
+	// Working with Duplicate Keys
+	//
+	int getNumDataMembers(const char *key) const;
+	const char * getStringValue(const char *name, int index) const;
+	void addStringValue(const char *name, const char *value);
+	bool deleteData(const char *name, int index);
+
+
+
+};
+}} // end namespace rude::config
+#endif
+
diff --git a/rudeconfig/src/DataLine.cpp b/rudeconfig/src/DataLine.cpp
new file mode 100644
index 0000000..0503886
--- /dev/null
+++ b/rudeconfig/src/DataLine.cpp
@@ -0,0 +1,52 @@
+// DataLine.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "DataLine.h"
+
+namespace rude{
+namespace config{
+
+DataLine::DataLine()
+{
+	d_isDeleted = false;
+}
+
+bool DataLine::isDeleted() const
+{
+	return d_isDeleted;
+}
+
+void DataLine::isDeleted(bool isit)
+{
+	d_isDeleted = isit;
+}
+
+DataLine::~DataLine()
+{
+
+}
+
+}} // end namespace rude::config
+
diff --git a/rudeconfig/src/DataLine.h b/rudeconfig/src/DataLine.h
new file mode 100644
index 0000000..032bbe1
--- /dev/null
+++ b/rudeconfig/src/DataLine.h
@@ -0,0 +1,63 @@
+// DataLine.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#ifndef INCLUDED_DataLine_H
+#define INCLUDED_DataLine_H
+
+#ifndef INCLUDED_AbstractData_H
+#include "AbstractData.h"
+#endif
+
+namespace rude{
+namespace config{
+
+class DataLine: public AbstractData{
+
+	bool d_isDeleted;
+	
+protected:
+
+	DataLine();
+
+public:
+	
+	void acceptWriter(AbstractWriter& writer) const = 0;
+
+	//=
+	// Returns true if the data member has been deleted
+	//=
+	bool isDeleted() const;
+
+	//=
+	// Sets / unsets the deleted status of the data member
+	//=
+	void isDeleted(bool isit);
+
+	virtual ~DataLine();
+	
+};
+
+}} // end namespace rude::config
+
+#endif
+
diff --git a/rudeconfig/src/File.cpp b/rudeconfig/src/File.cpp
new file mode 100644
index 0000000..abaa96e
--- /dev/null
+++ b/rudeconfig/src/File.cpp
@@ -0,0 +1,341 @@
+// File.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#include "../config.h"
+
+#include "File.h"
+
+#ifndef INCLUDED_Section_H
+#include "Section.h"
+#endif
+
+#ifndef INCLUDED_AbstractWriter_H
+#include "AbstractWriter.h"
+#endif
+
+using namespace std;
+
+namespace rude{
+namespace config{
+
+File::File()
+{
+	d_currentSection = new Section("", 0);
+	d_sections.push_back(d_currentSection);
+	std::string empty = "";
+	d_sectionmap[empty] = d_currentSection;
+}
+
+
+File::~File()
+{
+	std::vector<Section*>::iterator iter;
+	for(iter = d_sections.begin(); iter != d_sections.end(); iter++)
+	{
+		delete (*iter);
+	}
+}
+
+void File::acceptWriter(AbstractWriter& writer) const
+{
+	writer.visitFile(*this);
+
+	// All the data members are responsible for printing themselves out.
+	// They are also responsible for knowing what to do when they are
+	// marked as deleted and when commentchar / delimiter are 0
+	//
+	std::vector<Section*>::iterator iter;
+	for(iter = d_sections.begin(); iter != d_sections.end(); iter++)
+	{
+		(*iter)->acceptWriter(writer);
+	}
+}
+void File::clear()
+{
+	std::vector<Section*>::iterator iter;
+	for(iter = d_sections.begin(); iter != d_sections.end(); iter++)
+	{
+		delete (*iter);
+	}
+	d_sections.clear();
+	d_sectionmap.clear();
+
+
+	// We create one to begin with, swo that we always
+	// have a valid d_currentSection to work with.
+	d_currentSection = new Section("", 0);
+	d_sections.push_back(d_currentSection);
+	std::string empty = "";
+	d_sectionmap[empty] = d_currentSection;
+
+}
+const char * File::getStringValue(const char *name) const
+{
+	if(d_currentSection)
+	{
+		return d_currentSection->getValue(name);
+	}
+	return 0;
+}
+
+bool File::deleteData(const char *name)
+{
+	if(d_currentSection)
+	{
+		return d_currentSection->deleteData(name);
+	}
+	return false;
+}
+
+void File::setStringValue(const char *name, const char *value)
+{
+	if(d_currentSection)
+	{
+		d_currentSection->setValue(name, value);
+	}
+}
+
+int File::getNumDataMembers() const
+{
+	if(d_currentSection)
+	{
+		return d_currentSection->getNumDataMembers();
+	}
+	return 0;
+}
+
+const char *File::getDataNameAt(int index) const
+{
+	if(d_currentSection)
+	{
+		return d_currentSection->getDataNameAt(index);
+	}
+	return 0;
+}
+
+const char *File::getDataValueAt(int index) const
+{
+	if(d_currentSection)
+	{
+		return d_currentSection->getDataValueAt(index);
+	}
+	return 0;
+}
+
+
+int File::getNumSourceDestMembers() const
+{
+  if(d_currentSection)
+    {
+    return d_currentSection->getNumSourceDestMembers();
+    }
+  return 0;
+}
+
+const char *File::getSrcAppAt(int index) const
+{
+  if(d_currentSection)
+    {
+      return d_currentSection->getSrcAppAt(index);
+    }
+  return 0;
+}
+
+const char *File::getDestAppAt(int index) const
+{
+  if(d_currentSection)
+    {
+    return d_currentSection->getDestAppAt(index);
+    }
+  return 0;
+}
+
+const char *File::getSrcObjAt(int index) const
+{
+  if(d_currentSection)
+    {
+      return d_currentSection->getSrcObjAt(index);
+    }
+  return 0;
+}
+
+const char *File::getDestObjAt(int index) const
+{
+  if(d_currentSection)
+    {
+    return d_currentSection->getDestObjAt(index);
+    }
+  return 0;
+}
+
+const char *File::getWidthAt(int index) const
+{
+  if(d_currentSection)
+    {
+    return d_currentSection->getWidthAt(index);
+    }
+  return 0;
+}
+const char *File::getCommTypeAt(int index) const
+{
+	if(d_currentSection)
+	{
+		return d_currentSection->getCommTypeAt(index);
+	}
+	return 0;
+
+}
+const char *File::getProcMethodAt(int index) const
+{
+	if(d_currentSection)
+	{
+		return d_currentSection->getProcMethodAt(index);
+	}
+	return 0;
+}
+bool File::exists(const char *name) const
+{
+	if(d_currentSection)
+	{
+		return d_currentSection->exists(name);
+	}
+	return 0;
+}
+
+int File::getNumSections() const
+{
+	int len = d_sections.size();
+	int count = 0;
+	for(int x=0; x< len; x++)
+	{
+		Section *theSection = d_sections[x];
+		if(!theSection->isDeleted())
+		{
+			count++;
+		}
+	}
+	return count;
+}
+
+const char *File::getSectionNameAt(int index) const
+{
+	int len = d_sections.size();
+	int position = 0;
+	for(int x=0; x< len; x++)
+	{
+		Section *theSection = d_sections[x];
+		if(!theSection->isDeleted())
+		{
+			if(position == index)
+			{
+				return theSection->getSectionName();
+			}
+			position++;
+		}
+	}
+	return 0;
+}
+
+bool File::setSection(const char *sectionname, bool shouldCreate)
+{
+	if(sectionname)
+	{
+		std::string name=sectionname;
+		Section *thesection = d_sectionmap[name];
+		if(thesection)
+		{
+			if(!thesection->isDeleted())
+			{
+				d_currentSection = thesection;
+				return true;
+			}
+			else
+			{
+				if(shouldCreate)
+				{
+					// revive the deleted section
+					// 
+					thesection->isDeleted(false);
+					d_currentSection = thesection;
+					return true;
+				}
+				return false;
+			}
+		}
+		else
+		{
+			// The section could not be found.....
+			// 
+			if(shouldCreate)
+			{
+				d_currentSection = new Section(sectionname, 0);
+				std::string stringname = sectionname;
+				d_sections.push_back(d_currentSection);
+				d_sectionmap[stringname] = d_currentSection;
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+Section *File::getSection(const char *sectionname)
+{
+	setSection(sectionname, true);
+	return d_currentSection;
+}
+
+bool File::deleteSection(const char *sectionname)
+{
+	if(sectionname)
+	{
+		std::string name=sectionname;
+		Section *thesection = d_sectionmap[name];
+		if(thesection)
+		{
+				thesection->isDeleted(true);
+				// Here is the interesting part, 
+				// By deleting the current section, we have effectively
+				// deleted all of its data members...
+				// but if we are deleting the current section, 
+				// then we need to change the current section to
+				// the default one - the "" section, 
+				// and make sure that that section is undeleted....
+				// because we always need a current section.
+				if(thesection == d_currentSection)
+				{
+					return setSection("", true);
+				}
+				return true;
+
+		}
+		// The section could not be found.....
+	}
+	return false;	
+}
+
+
+
+}} // end namespace rude::config
+
diff --git a/rudeconfig/src/File.h b/rudeconfig/src/File.h
new file mode 100644
index 0000000..5760285
--- /dev/null
+++ b/rudeconfig/src/File.h
@@ -0,0 +1,97 @@
+// File.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#ifndef INCLUDED_File_H
+#define INCLUDED_File_H
+
+#ifndef INCLUDED_AbstractData_H
+#include "AbstractData.h"
+#endif
+
+#ifndef INCLUDED_VECTOR
+#include <vector>
+#define INCLUDED_VECTOR
+#endif
+
+#ifndef INCLUDED_MAP
+#include <map>
+#define INCLUDED_MAP
+#endif
+
+#include <string>
+
+using namespace rude::config;
+
+namespace rude{
+namespace config{
+
+class Section;
+
+class File: public AbstractData{
+
+private:
+	Section *d_currentSection;
+	mutable std::vector<Section*> d_sections;
+	mutable std::map<std::string, Section*> d_sectionmap;
+
+public:
+
+	File();
+	~File();
+	void acceptWriter(AbstractWriter& writer) const;
+	void clear();
+	const char * getStringValue(const char *name) const;
+	bool deleteData(const char *name);
+	void setStringValue(const char *name, const char *value);
+	int getNumDataMembers() const;
+
+        int getNumSourceDestMembers() const;
+        const char *getSrcObjAt(int index) const;
+        const char *getDestObjAt(int index) const;
+        const char *getSrcAppAt(int index) const;
+        const char *getDestAppAt(int index) const;
+        const char *getWidthAt(int index) const;
+        /* remedius
+         */
+        const char *getCommTypeAt(int index) const;
+        /* remedius
+         */
+        const char *getProcMethodAt(int index) const;
+
+	const char *getDataNameAt(int index) const;
+	const char *getDataValueAt(int index) const;
+	bool exists(const char *name) const;
+	int getNumSections() const;
+	const char *getSectionNameAt(int index) const;
+	bool setSection(const char *sectionname, bool shouldCreate);
+	bool deleteSection(const char *sectionname);
+
+	Section *getSection(const char *sectionname);
+
+};
+
+}} // end namespace rude::config
+
+#endif
+
diff --git a/rudeconfig/src/KeyValue.cpp b/rudeconfig/src/KeyValue.cpp
new file mode 100644
index 0000000..a7c8612
--- /dev/null
+++ b/rudeconfig/src/KeyValue.cpp
@@ -0,0 +1,96 @@
+// KeyValue.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#include "../config.h"
+
+#include "KeyValue.h"
+
+#ifndef INCLUDED_AbstractWriter_H
+#include "AbstractWriter.h"
+#endif
+
+#ifndef INCLUDED_CSTDIO
+#include <cstdio>
+#define INCLUDED_CSTDIO
+#endif
+
+using namespace std;
+namespace rude{
+namespace config{
+
+KeyValue::KeyValue()
+{
+	d_name = "";
+	d_value = "";
+	d_comment = "";
+}
+
+KeyValue::KeyValue(const char *name, const char *value, const char *comment)
+{
+	d_name = name ? name : "";
+	d_value = value ? value : "";
+	d_comment = comment ? comment : "";
+}
+
+void KeyValue::acceptWriter(AbstractWriter& writer) const
+{
+	writer.visitKeyValue(*this);
+}
+
+const char *KeyValue::getName() const
+{
+	return d_name.c_str();
+}
+
+const char *KeyValue::getValue() const
+{
+	return d_value.c_str();
+}
+
+const char *KeyValue::getComment() const
+{
+	return d_comment.c_str();
+}
+
+void KeyValue::setName(const char *name)
+{
+	d_name = name ? name : "";
+}
+
+void KeyValue::setValue(const char *value)
+{
+	d_value = value ? value : "";
+}
+
+void KeyValue::setComment(const char *comment)
+{
+	d_comment = comment ? comment : "";
+}
+
+KeyValue::~KeyValue()
+{
+
+}
+}} // end namespace rude::config
+
diff --git a/rudeconfig/src/KeyValue.h b/rudeconfig/src/KeyValue.h
new file mode 100644
index 0000000..2d8714a
--- /dev/null
+++ b/rudeconfig/src/KeyValue.h
@@ -0,0 +1,123 @@
+// KeyValue.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#ifndef INCLUDED_KeyValue_H
+#define INCLUDED_KeyValue_H
+
+#ifndef INCLUDED_DataLine_H
+#include "DataLine.h"
+#endif
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+namespace rude{
+namespace config{
+//=
+// KeyValue represents a single line/entry in a configuration file.
+// It can represent whitespace, a comment, or key=value data.
+// 
+// <B>Current Limitations</B>
+// <ul>
+// <li> <b>Data Names:</b> it is assumed that the names for entries are valid.  Invalid names are not detected.
+//						A name containing the delimiter or comment character is invalid.
+//						A name containing newline information is invalid.
+// Future releases should either detect and reject invalid names, or use an escape mechanism such as backslashing
+// to allow invalid characters to appear within a name.
+// 
+// <li> <b>Data Values:</b> Same as data names. (see above)
+// </ul>
+//=
+class KeyValue: public DataLine{
+
+
+	std::string d_name;
+	std::string d_value;
+	std::string d_comment;
+
+public:
+
+	// default constructor
+	KeyValue();
+	KeyValue(const char *name, const char *value, const char *comment);
+	
+	void acceptWriter(AbstractWriter& writer) const;
+
+	//= 
+	// Returns the name of the data member
+	// Will return the name even if the data member is flagged as being deleted or a comment
+	// Always returns at least the empty string, will never return null.
+	//=
+	const char *getName() const;
+
+	//= 
+	// Returns the string value of the data member
+	// Will return the value even if the data member is flagged as being deleted or a comment
+	// Always returns at least the empty string, will never return null.
+	//=
+	const char *getValue() const;
+
+	//= 
+	// Returns the comment associated with the data member
+	// Will return the comment even if the data member is flagged as being deleted
+	// Always returns at least the empty string, will never return null.
+	//=
+	const char *getComment() const;
+
+	//= 
+	// Sets the name of the data member
+	// Will set the name even if the data member is flagged as being deleted or a comment
+	// Accepts null
+	//=
+	void setName(const char *name);
+
+	//= 
+	// Sets the string value of the data member
+	// Will set the value even if the data member is flagged as being deleted or a comment
+	// Accepts null
+	//=
+	void setValue(const char *value); // un-deletes if previously deleted.....
+
+	//= 
+	// Sets the comment associated with the data member
+	// Will set the comment even if the data member is flagged as being deleted
+	// Accepts null
+	//=
+	void setComment(const char *comment);
+	
+	~KeyValue();
+	
+};
+
+}} // end namespace rude::config
+
+#endif
+
diff --git a/rudeconfig/src/ParserJuly2004.cpp b/rudeconfig/src/ParserJuly2004.cpp
new file mode 100644
index 0000000..d45e7ed
--- /dev/null
+++ b/rudeconfig/src/ParserJuly2004.cpp
@@ -0,0 +1,1206 @@
+// ParserJuly2004.cc
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "ParserJuly2004.h"
+
+#ifndef INCLUDED_AbstractOrganiser_h
+#include "AbstractOrganiser.h"
+#endif
+
+#ifndef INCLUDED_CCTYPE
+#include <cctype>
+#define INCLUDED_CCTYPE
+#endif
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+#include <cstdio>
+
+using namespace rude::config;
+using namespace std;
+
+namespace rude{
+namespace config{
+
+enum SectionState{ STARTSECTION, SECTIONID, ESCAPEID, ENDSECTIONID, SECTIONCOMMENT, FOUNDIDONLY, FOUNDIDCOMMENT, SECTIONERROR, ENDSECTION };
+/* remedius
+ * GETCOMMTYPE, GETPROCMETHOD were added in order to support runtime configuration options for choosing communication type and pre-/post-processing method
+ */
+enum KeyValueState{ KEY, KEYESCAPE, STARTVALUE, COMMENT, FINDCOMMENT, KVERROR, ENDKV, VALUE, QUOTEVALUE, NONQUOTEVALUE, QUOTEESCAPE, NONQUOTEESCAPE, ENDKEYVALUE, LEFTARROW, RIGHTARROW, GETSOURCE, GETDEST, GETWIDTH, GETCOMMTYPE, GETPROCMETHOD, SDCOMMENT, ENDSOURCEDEST};
+
+void ParserJuly2004::stripTrailing(std::string& buffer)
+{
+	int bufferLength = buffer.size();
+
+	for (int x = bufferLength - 1; x >= 0; x--)
+	{
+		char c = buffer[x];
+
+		if (isspace(c))
+		{
+			buffer.erase(x);
+		}
+		else
+		{
+			break;
+		}
+	}
+}
+
+
+bool ParserJuly2004::isEOL(char c)
+{
+	return (c == '\r' || c == '\f' || c == '\n');
+}
+
+bool ParserJuly2004::chompEOL(std::istream& inputstream)
+{
+		char c = inputstream.peek();
+		if(isEOL(c))
+		{
+			inputstream.get();
+			char next_c = inputstream.peek();
+			if( (c != next_c) && isEOL(next_c) )
+			{
+				inputstream.get();
+			}
+		}
+		return true;
+}
+
+bool ParserJuly2004::parse(std::istream& infile, AbstractOrganiser& organiser)
+{
+	if (d_delimiter == '\\' || isEOL(d_delimiter) || d_delimiter == d_commentchar || d_delimiter == '[')
+	{
+		setError("110", "Illegal delimiter.");
+		return false;
+	}
+
+	if (d_commentchar == '\\' || d_commentchar == '"' || isspace(d_commentchar))
+	{
+		setError("111", "Illegal comment character.");
+		return false;
+	}
+	
+	register int c;
+		
+	// eof only gets set when error_flag is set on previous operation
+	// as such, you need to peek() at the end ot the while loop
+	// in order for eof to happen when you want it to!!
+	// one peek() triggers infile.eof(), but it does not reveal it!!!!
+	// you gotta call peek() twice.
+	//
+	while( (c = infile.peek()) != EOF)
+	{
+		// We're looking for:
+		// '[' beggining of section
+		// '#' (d_commentchar) comment character
+		// any non-whitespace character
+
+		if(isspace(c))
+		{
+			std::string whitespace = "";
+
+			while(c != EOF && isspace(c))
+			{
+				whitespace += infile.get();
+				c = infile.peek();
+			}
+			organiser.foundWhiteSpace(whitespace.c_str());
+		}
+		else if(c == '[')
+		{
+			// discard '[' character
+			//
+			infile.get();
+				
+			register SectionState sectionState = STARTSECTION;
+
+			std::string sectionID = "";
+			std::string comment = "";
+				
+			while (sectionState != ENDSECTION)
+			{						
+				switch (sectionState)
+				{
+					case STARTSECTION:
+					{
+							c = infile.peek();
+							if(c == EOF)
+							{
+								setError("102", "End of stream found before section ID.");
+								sectionState = SECTIONERROR;
+							}
+							else if(isEOL(c))
+							{
+								setError("101", "End of line found before section ID.");
+								sectionState = SECTIONERROR;   
+							}
+							else if(c == ' ' || c == '\t')
+							{
+								// discard whitespace
+								//
+								infile.get();
+									
+								// LOOP
+							}
+							else if(c == ']')
+							{
+								// discard ']'
+								//
+								infile.get();
+								
+								sectionState = ENDSECTIONID;
+							}
+							else
+							{
+								sectionState = SECTIONID;
+							}
+							break;
+					}
+					case SECTIONID:
+					{
+							c = infile.peek();
+							if(c == EOF)
+							{
+								setError("104", "End of stream found before end-of-section marker.");
+								sectionState = SECTIONERROR;
+							}
+							else if(isEOL(c))
+							{
+								setError("103", "End of line found before end-of-section marker.");
+								sectionState = SECTIONERROR;	     
+							}
+							else if(c == '\\')
+							{
+								// discard backslash
+								//
+								infile.get();
+
+								sectionState = ESCAPEID;
+							}
+							else if(c == ']')
+							{
+								// discard ']'
+								//
+								infile.get();
+
+								// Strip Trailing Whitespace from ID
+								//
+								stripTrailing(sectionID);
+									
+								sectionState = ENDSECTIONID;
+							}
+							else
+							{
+								sectionID += infile.get();
+
+								// LOOP
+							}
+							break;
+					}
+					case ESCAPEID:
+					{
+							c = infile.peek();
+							if(c == EOF)
+							{
+								setError("107", "End of stream found after un-escaped backslash.");
+								sectionState = SECTIONERROR;
+							}
+							else if(isEOL(c))
+							{
+								setError("108", "Escaped new-line is not allowed in section ID or key.");
+								sectionState = SECTIONERROR;
+							}
+							else
+							{
+								sectionID += infile.get();
+								sectionState = SECTIONID;
+							}
+							break;
+					}
+					case ENDSECTIONID:
+					{
+							c = infile.peek();
+							if(c == EOF || isEOL(c))
+							{
+								sectionState = FOUNDIDONLY;				
+							}
+							else if(d_commentchar != 0 && c == d_commentchar)
+							{
+								// discard '#'
+								//
+								infile.get();
+									
+								sectionState = SECTIONCOMMENT;								
+							}
+							else if(c == ' ' || c == '\t')
+							{
+								// discard whitespace
+								//
+								infile.get();
+									
+								// LOOP
+							}
+							else
+							{
+								setError("105", "Illegal character found after end-of-section marker.");
+								sectionState = SECTIONERROR;
+							}
+							break;
+					}
+					case SECTIONCOMMENT:
+					{
+							c = infile.peek();
+							if(c == EOF || isEOL(c))
+							{
+								sectionState = FOUNDIDCOMMENT;
+								stripTrailing(comment);
+							}
+							else
+							{
+								// append to comment
+								//
+								comment += infile.get();
+									
+								// LOOP			
+							}
+							break;
+					}
+					case SECTIONERROR:
+					case ENDSECTION: // dummy
+					{
+						return false;
+					}
+					case FOUNDIDONLY:
+					{
+						organiser.foundSection(sectionID.c_str(), 0);
+						chompEOL(infile);
+						sectionState = ENDSECTION;
+						break;
+					}
+					case FOUNDIDCOMMENT:
+					{
+						organiser.foundSection(sectionID.c_str(), comment.c_str());
+						chompEOL(infile);
+						sectionState = ENDSECTION;
+						break;
+					}
+				}
+			}
+		}
+		else if(c == d_commentchar)
+		{
+			// found a comment line
+			// discard the comment character
+			//
+			infile.get();
+				
+			// put the rest of the line into a string
+			//
+			std::string line="";
+			while(infile.good())
+			{
+				c=infile.get();
+				if( isEOL(c))
+				{
+					break;
+				}
+				line += c;
+			}
+
+			chompEOL(infile);
+			
+			// PROCESS THE COMMENT LINE
+			//
+			stripTrailing(line);
+			organiser.foundComment(line.c_str());
+		}
+		else
+		{
+			register KeyValueState kvState = KEY;
+			std::string key = "";
+			std::string value = "";
+			std::string comment = "";
+
+
+                        // Added to handle source -> dest
+
+                        std::string srcApp = "";
+                        std::string srcObj = "";
+                        std::string destApp = "";
+                        std::string destObj = "";
+                        std::string width = "";
+                        /* remedius */
+                        std::string commType = "";
+                        /* remedius */
+                        std::string procMethod = "";
+
+			while (kvState != ENDKEYVALUE)
+			{						
+				
+				switch (kvState)
+				{
+					case KEY:
+					{
+                                          //std::cout << "KEY\n";
+
+							int c = infile.peek();
+							
+							if(c == EOF || isEOL(c))
+							{
+								kvState = ENDKV;
+							}
+							else if(d_delimiter && c == d_delimiter)
+							{
+								// discard '='
+								//
+								infile.get();
+
+								kvState = STARTVALUE;
+							}
+							else if(!d_delimiter && (c == ' ' || c == '\t'))
+							{
+								// discard whitespace
+								//
+								infile.get();
+								kvState = STARTVALUE;
+							}
+							else if(d_commentchar != 0 && c == d_commentchar)
+							{
+								// discard '#'
+								//
+								infile.get();
+
+								kvState = COMMENT;
+							}
+							else if(c == '\\')
+							{
+								// discard '\\'
+								//
+								infile.get();
+
+								kvState = KEYESCAPE;
+							}
+                                                        else if(c == '-')
+                                                          {
+                                                            // Is it -> ??
+                                                            infile.get();
+                                                            c = infile.peek();
+
+                                                            if(c == '>')
+                                                              {
+                                                                infile.get();
+
+                                                                kvState = RIGHTARROW;
+                                                                // We need to split up the key into srcApp.srcObj and store them
+                                                                size_t dotPos = key.find_first_of('.');
+
+                                                                if(dotPos != string::npos)
+                                                                  {
+                                                                    srcApp = key.substr(0,dotPos);
+                                                                    srcObj = key.substr(dotPos+1,key.length()-dotPos-1);
+
+                                                                    //std::cout << "Found srcApp: " << srcApp << " srcObj: " << srcObj << "\n";
+
+                                                                  }
+                                                                else
+                                                                  {
+                                                                    srcApp = "";
+                                                                    srcObj = key;
+                                                                  }
+                                                              }
+                                                            else
+                                                              {
+                                                                key += '-';
+                                                              }
+                                                          }
+                                                        else if(c == '<')
+                                                          {
+                                                            // IS it <- ??
+                                                            infile.get();
+                                                            c = infile.peek();
+
+                                                            if(c == '-')
+                                                              {
+                                                                infile.get();
+
+                                                                kvState = LEFTARROW;
+                                                                // We need to split up the key into destApp.destObj and store them
+                                                                size_t dotPos = key.find_first_of('.');
+
+                                                                if(dotPos != string::npos)
+                                                                  {
+
+                                                                    destApp = key.substr(0,dotPos);
+                                                                    destObj = key.substr(dotPos+1,key.length()-dotPos-1);
+
+                                                                    //std::cout << "Found destApp: " << destApp << " destObj: " << destObj << "\n";
+
+                                                                  }
+                                                                else
+                                                                  {
+                                                                    destApp = "";
+                                                                    destObj = key;
+                                                                  }
+                                                              }
+                                                            else
+                                                              {
+                                                                key += '<';
+                                                              }
+                                                          }
+							else
+							{
+								// append to key
+								//
+								key += infile.get();
+									
+								// LOOP			
+							}
+							break;
+					}
+					case KEYESCAPE:
+					{
+                                          //std::cout << "KEYESCAPE\n";
+							int c = infile.peek();
+							if(c == EOF)
+							{
+								setError("107", "End of stream found after un-escaped backslash.");
+								kvState = KVERROR;
+							}
+							else if(isEOL(c))
+							{
+								setError("108", "Escaped new-line is not allowed in key.");
+								kvState = KVERROR;
+							}
+							else
+							{
+								// append to key
+								//
+								key += infile.get();
+
+								kvState = KEY;
+							}
+							break;
+					}
+					case STARTVALUE:
+					{
+                                          //std::cout << "STARTVALUE\n";
+							int c = infile.peek();
+
+							if(c == EOF || isEOL(c))
+							{
+								kvState = ENDKV;
+							}
+							else if(d_commentchar != 0 && c == d_commentchar)
+							{
+								// discard '#'
+								//
+								infile.get();
+
+								kvState = COMMENT;
+							}
+							else if(c == ' ' || c == '\t')
+							{
+								// discard whitespace
+								//
+								infile.get();
+
+								// LOOP
+							}
+							else
+							{
+								kvState = VALUE;	
+							}
+							break;
+					}
+					case KVERROR:
+					case ENDKEYVALUE: // dummy for compiler
+					{
+                                          //std::cout << "KVERROR\n";
+							return false;
+					}
+					case FINDCOMMENT:
+					{
+                                          
+                                          //std::cout << "FINDCOMMENT\n";
+							int c = infile.peek();
+
+							if(c == EOF || isEOL(c))
+							{
+								kvState = ENDKV;
+							}
+							else if(d_commentchar != 0 && c == d_commentchar)
+							{
+								// discard '#'
+								//
+								infile.get();
+
+								kvState = COMMENT;
+							}
+							else if(c == ' ' || c == '\t')
+							{
+								// discard whitespace
+								//
+								infile.get();
+
+								// LOOP
+							}
+							else
+							{
+								setError("109", "Illegal Character Found after quoted value.");
+								kvState = KVERROR;	
+							}
+							break;
+					}
+					case COMMENT:
+					{
+                                          //std::cout << "COMMENT\n";
+
+							int c = infile.peek();
+
+							if(c == EOF || isEOL(c))
+							{
+								stripTrailing(comment);
+								kvState = ENDKV;
+							}
+							else
+							{
+								// Append to comment
+								//
+								comment += infile.get();
+
+								// LOOP	
+							}
+							break;
+					}
+					case VALUE:
+					{
+                                          //std::cout << "VALUE\n";
+
+						int c = infile.peek();
+						if(c == '"')
+						{
+							// discard '"'
+							//
+							infile.get();
+
+							kvState = QUOTEVALUE;
+						}
+						else
+						{
+							kvState = NONQUOTEVALUE;
+						}
+						break;
+					}
+					case QUOTEVALUE:
+					{
+                                          //std::cout << "QUOTEVALUE\n";
+							int c = infile.peek();
+							if(c == EOF)
+							{
+								setError("106", "End of stream found before final quote (\") in value.");
+								kvState = KVERROR;
+							}
+							else if(c == '"')
+							{
+								// discard '"'
+								//
+								infile.get();
+
+								kvState = FINDCOMMENT;
+							}
+							else if(c == '\\')
+							{
+								// discard backslash
+								//
+								infile.get();
+
+								kvState = QUOTEESCAPE;
+							}
+							else
+							{
+								// append to value
+								//
+								value += infile.get();
+
+								// LOOP
+							}
+							break;
+					}
+					case QUOTEESCAPE:
+					{
+                                          //std::cout << "QUOTEESCAPE\n";
+
+							int c = infile.peek();
+							if(c == EOF)
+							{
+								setError("107", "End of stream found after un-escaped backslash.");
+								kvState = KVERROR;
+							}
+							else
+							{
+								// append to value
+								//
+								value += infile.get();
+
+								kvState = QUOTEVALUE;
+							}
+							break;
+					}
+					case NONQUOTEVALUE:
+					{
+                                          //std::cout << "NONQUOTEVALUE\n";
+							int c = infile.peek();
+
+							if(c == EOF || isEOL(c))
+							{
+								stripTrailing(value);
+
+								kvState = ENDKV;
+							}
+							else if(d_commentchar != 0 && c == d_commentchar)
+							{
+								// discard '#'
+								//
+								infile.get();
+								
+								stripTrailing(value);
+								
+								kvState = COMMENT;
+							}
+							else if(c == '\\')
+							{
+								// discard backslash
+								//
+								infile.get();
+
+								kvState = NONQUOTEESCAPE;
+							}
+							else
+							{
+								// append to value
+								//
+								value += infile.get();
+
+								// LOOP
+							}
+							break;
+					}
+					case NONQUOTEESCAPE:
+					{
+                                          //std::cout << "NONQUOTEESCAPE\n";
+
+							int c = infile.peek();
+							if(c == EOF)
+							{
+								setError("107", "End of stream found after un-escaped backslash.");
+								kvState = KVERROR;
+							}
+							else
+							{
+								// append to value
+								//
+								c = infile.get();
+								value += c;
+
+								// SPECIAL CASE FOR ESCAPED CRLFs:
+								//
+								// if c is newline and next character is also newline, 
+								// we keep both of them if they are different forms of newline
+								// 
+								char next_c = infile.peek();
+								if(isEOL(c) && isEOL(next_c) && (c != next_c))
+								{
+									value += infile.get();
+								} 
+								kvState = NONQUOTEVALUE;
+							}
+							break;
+					}				
+					case ENDKV:
+                                          {
+                                            //std::cout << "ENDKV\n";
+
+                                            chompEOL(infile);
+                                            
+                                            stripTrailing(key);
+                                            organiser.foundData(key.c_str(), value.c_str(), comment.c_str());
+                                            
+                                            kvState = ENDKEYVALUE;
+                                            break;
+                                          }
+                                        case LEFTARROW:
+                                          {
+                                            //std::cout << "LEFTARROW\n";
+
+                                            int c = infile.peek();
+
+                                            if(c == EOF || isEOL(c))
+                                              {
+                                                kvState = ENDSOURCEDEST;
+
+                                                stripTrailing(value);
+
+                                                size_t dotPos = value.find_first_of('.');
+
+                                                if(dotPos != string::npos)
+                                                  {
+                                                    srcApp = value.substr(0,dotPos);
+                                                    srcObj = value.substr(dotPos+1,value.length()-dotPos-1);
+
+                                                    //std::cout << "srcApp: " << srcApp << " srcObj: " << srcObj << "\n";
+                                                  }
+                                                else
+                                                  {
+                                                    //std::cout << "srcObj: " << value << "\n";
+                                                    
+                                                    srcApp = "";
+                                                    srcObj = value;
+                                                  }
+                                              }
+                                            else if(c == ' ' || c == '\t')
+                                              {
+                                                // Discard whitespace
+                                                infile.get();
+                                              }
+                                            else if(d_commentchar != 0 && c == d_commentchar)
+                                              {
+                                                // discard '#'
+                                                infile.get();
+                                                
+                                                kvState = SDCOMMENT;
+                                              }
+                                            else 
+                                              {
+                                              kvState = GETSOURCE;
+                                              }
+
+
+                                            break;
+                                          }
+                                        case RIGHTARROW:
+                                          {
+                                            //std::cout << "RIGHTARROW\n";
+
+                                            int c = infile.peek();
+
+                                            if(c == EOF || isEOL(c))
+                                              {
+                                                kvState = ENDSOURCEDEST;
+
+                                                stripTrailing(value);                                                
+
+                                                size_t dotPos = value.find_first_of('.');
+
+                                                if(dotPos != string::npos)
+                                                  {
+                                                    destApp = value.substr(0,dotPos);
+                                                    destObj = value.substr(dotPos+1,value.length()-dotPos-1);
+                                                  }
+                                                else
+                                                  {
+                                                    destApp = "";
+                                                    destObj = value;
+                                                  }
+                                              }
+                                            else if(c == ' ' || c == '\t')
+                                              {
+                                                // Discard whitespace
+                                                infile.get();
+                                              }
+                                            else if(d_commentchar != 0 && c == d_commentchar)
+                                              {
+                                                // discard '#'
+                                                infile.get();
+                                                
+                                                kvState = SDCOMMENT;
+                                              }
+                                            else 
+                                              {
+                                              kvState = GETDEST;
+                                              }
+
+                                            break;
+                                          }
+                                        case GETSOURCE:
+                                          {
+                                            //std::cout << "GETSOURCE\n";
+
+                                            int c = infile.peek();
+
+                                            if(c == EOF || isEOL(c))
+                                              {
+                                                stripTrailing(value);
+
+                                                kvState = ENDSOURCEDEST;
+
+                                                size_t dotPos = value.find_first_of('.');
+
+                                                if(dotPos != string::npos)
+                                                  {
+                                                    srcApp = value.substr(0,dotPos);
+                                                    srcObj = value.substr(dotPos+1,value.length()-dotPos-1);
+
+                                                    //std::cout << "srcApp: " << srcApp << " srcObj: " << srcObj << "\n";
+                                                  }
+                                                else
+                                                  {
+                                                    //std::cout << "srcObj: " << value << "\n";
+                                                    
+                                                    srcApp = "";
+                                                    srcObj = value;
+                                                  }
+                                              }
+                                            else if((d_commentchar != 0 && c == d_commentchar) || c == '[')
+                                              {
+                                                // discard '#' or '['
+                                                //
+                                                infile.get();
+                                                
+                                                stripTrailing(value);
+                                                
+                                                size_t dotPos = value.find_first_of('.');
+
+                                                if(dotPos != string::npos)
+                                                  {
+                                                    srcApp = value.substr(0,dotPos);
+                                                    srcObj = value.substr(dotPos+1,value.length()-dotPos-1);
+
+                                                    //std::cout << "srcApp: " << srcApp << " srcObj: " << srcObj << "\n";
+                                                  }
+                                                else
+                                                  {
+                                                    //std::cout << "srcObj: " << value << "\n";
+                                                    
+                                                    srcApp = "";
+                                                    srcObj = value;
+                                                  }
+
+                                                // Which one was it, comment about to start or width info?
+                                                if(c == '[') 
+                                                  kvState = GETWIDTH;
+                                                else
+                                                  kvState = SDCOMMENT;
+                                              }
+                                            else
+                                              {
+                                                // append to value (temp storage for 
+                                                //
+                                                value += infile.get();
+
+                                                // LOOP
+                                              }
+
+                                            break;
+                                          }
+                                        case GETDEST:
+                                          {
+
+                                            //std::cout << "GETDEST\n";
+
+                                            int c = infile.peek();
+
+                                            if(c == EOF || isEOL(c))
+                                              {
+                                                stripTrailing(value);
+
+                                                kvState = ENDSOURCEDEST;
+
+                                                size_t dotPos = value.find_first_of('.');
+
+                                                if(dotPos != string::npos)
+                                                  {
+                                                    destApp = value.substr(0,dotPos);
+                                                    destObj = value.substr(dotPos+1,value.length()-dotPos-1);
+
+                                                    //std::cout << "Found destApp: " << destApp << " destObj: " << destObj << "\n";
+                                                                    
+                                                  }
+                                                else
+                                                  {
+                                                    destApp = "";
+                                                    destObj = value;
+                                                  }
+                                              }
+                                            else if((d_commentchar != 0 && c == d_commentchar) || c == '[')
+                                              {
+                                                // discard '#' or '['
+                                                //
+                                                infile.get();
+                                                
+                                                stripTrailing(value);
+                                                
+                                                size_t dotPos = value.find_first_of('.');
+
+                                                if(dotPos != string::npos)
+                                                  {
+                                                    destApp = value.substr(0,dotPos);
+                                                    destObj = value.substr(dotPos+1,value.length()-dotPos-1);
+
+                                                    //std::cout << "Found destApp: " << destApp << " destObj: " << destObj << "\n";
+                                                                    
+                                                  }
+                                                else
+                                                  {
+                                                    destApp = "";
+                                                    destObj = value;
+                                                  }
+
+                                                // Which one was it, comment about to start or width info?
+                                                if(c == '[') 
+                                                  kvState = GETWIDTH;
+                                                else
+                                                  kvState = SDCOMMENT;
+                                              }
+                                            else
+                                              {
+                                                // append to value (temp storage for 
+                                                //
+                                                value += infile.get();
+
+                                                // LOOP
+                                              }
+
+                                            break;
+                                          }
+                                        case GETWIDTH:
+                                          {
+                                            //std::cout << "GETWIDTH\n";
+
+                                            int c = infile.peek();
+                                            
+                                            if(c == EOF || isEOL(c))
+                                              {
+                                                setError("901", "Partial width found. No terminating ']'.");
+                                                kvState = KVERROR;
+                                              }
+                                            else if(d_commentchar != 0 && c == d_commentchar)
+                                              {
+                                                // discard '#'
+                                                //
+                                                infile.get();
+
+                                                kvState = SDCOMMENT;
+                                              }
+                                            else if(c == ' ' || c == '\t')
+                                              {
+                                                // discard whitespace
+                                                //
+                                                infile.get();
+
+
+                                                c = infile.peek();
+
+                                                if('0' <= c && c <= '9' && width.length() > 0)
+                                                  {
+                                                    setError("902", "Two numbers detected in the width declaration.");
+                                                    kvState = KVERROR;
+                                                  }
+
+                                                // LOOP
+                                              }
+                                            /* remedius
+                                             * communication type (GETCOMMTYPE) and processing method(GETPROCMETHOD) parameters are optional.
+                                             */
+                                            else if(c == ',')
+                                            {
+                                            	stripTrailing(width);
+                                            	infile.get(); // Throw away ,
+                                            	kvState = GETCOMMTYPE;
+
+                                            }
+                                            else if(c == ']')
+                                              {
+                                                stripTrailing(width);
+                                                infile.get(); // Throw away ]
+                                                kvState = ENDSOURCEDEST;
+
+                                                // Ignoring any comments that might be here...
+                                              }
+                                            else if('0' <= c && c <= '9')
+                                              {
+                                                width += infile.get();
+                                              }
+                                            else {
+                                              setError("903", "Non integer number detected.");
+                                              kvState = KVERROR;
+                                            }
+                                            break;
+                                          }
+                                          /* remedius */
+                                        case GETCOMMTYPE:
+                                        {
+                                            int c = infile.peek();
+
+                                            if(c == EOF || isEOL(c))
+                                              {
+                                                setError("901", "Partial communication type is found. No terminating ']'.");
+                                                kvState = KVERROR;
+                                              }
+                                            else if(d_commentchar != 0 && c == d_commentchar)
+                                              {
+                                                // discard '#'
+                                                //
+                                                infile.get();
+
+                                                kvState = SDCOMMENT;
+                                              }
+                                            else if(c == ' ' || c == '\t')
+                                              {
+                                                // discard whitespace
+                                                //
+                                                infile.get();
+
+                                                // LOOP
+                                              }
+                                            else if(c == ']')
+                                              {
+                                                stripTrailing(commType);
+                                                infile.get(); // Throw away ]
+                                                kvState = ENDSOURCEDEST;
+
+                                                // Ignoring any comments that might be here...
+                                              }
+                                            else if(c == ',')
+                                            {
+                                            	stripTrailing(commType);
+                                            	infile.get(); // Throw away ,
+                                            	kvState = GETPROCMETHOD;
+                                            }
+                                            else
+                                              {
+                                                commType += infile.get();
+                                              }
+
+                                            break;
+
+                                        }
+                                        /* remedius */
+                                        case GETPROCMETHOD:
+                                        {
+                                        	int c = infile.peek();
+
+                                        	if(c == EOF || isEOL(c))
+                                        	{
+                                        		setError("901", "Partial processing mathod is found. No terminating ']'.");
+                                        		kvState = KVERROR;
+                                        	}
+                                        	else if(d_commentchar != 0 && c == d_commentchar)
+                                        	{
+                                        		// discard '#'
+                                        		//
+                                        		infile.get();
+
+                                        		kvState = SDCOMMENT;
+                                        	}
+                                        	else if(c == ' ' || c == '\t')
+                                        	{
+                                        		// discard whitespace
+                                        		//
+                                        		infile.get();
+
+                                        		// LOOP
+                                        	}
+                                        	else if(c == ']')
+                                        	{
+                                        		stripTrailing(commType);
+                                        		infile.get(); // Throw away ]
+                                        		kvState = ENDSOURCEDEST;
+
+                                        		// Ignoring any comments that might be here...
+                                        	}
+                                        	else if(c != ',')
+                                        	{
+                                        		procMethod += infile.get();
+                                        	}
+                                        	else
+                                        	{
+                                        		setError("904", "Unexpected symbol.");
+                                        		kvState = KVERROR;
+                                        	}
+
+                                        	break;
+
+                                        }
+                                        case SDCOMMENT:
+                                          {
+                                            //std::cout << "SDCOMMENT\n";
+
+                                            int c = infile.peek();
+
+                                            if(c == EOF || isEOL(c))
+                                              {
+                                                stripTrailing(comment);
+                                                kvState = ENDSOURCEDEST;
+                                              }
+                                            else
+                                              {
+                                                // Append to comment
+                                                //
+                                                comment += infile.get();
+                                                
+                                                // LOOP	
+                                              }
+                                            break;
+                                          }
+                                        case ENDSOURCEDEST:
+                                          {
+                                            //std::cout << "ENDSOURCEDEST\n";
+
+                                            chompEOL(infile);
+                                            
+                                            stripTrailing(srcApp);
+                                            stripTrailing(srcObj);
+                                            stripTrailing(destApp);
+                                            stripTrailing(destObj);
+                                            stripTrailing(width);
+                                            /* remedius */
+                                            stripTrailing(commType);
+                                            /* remedius */
+                                            stripTrailing(procMethod);
+                                            /* remedius */
+                                            organiser.foundSourceDest(srcApp.c_str(), srcObj.c_str(), destApp.c_str(), destObj.c_str(), width.c_str(), commType.c_str(), procMethod.c_str(), comment.c_str());
+                                            
+                                            kvState = ENDKEYVALUE;
+                                            break;
+                                          }
+
+
+				} // end switch
+			} // end while
+		}
+	}
+	return true;
+}
+
+}} // end namespaces
+
+
+
+
diff --git a/rudeconfig/src/ParserJuly2004.h b/rudeconfig/src/ParserJuly2004.h
new file mode 100644
index 0000000..7659f51
--- /dev/null
+++ b/rudeconfig/src/ParserJuly2004.h
@@ -0,0 +1,62 @@
+// ParserJuly2004.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#ifndef INPUT_ParserJuly2004_h
+#define INPUT_ParserJuly2004_h
+
+#ifndef INPUT_AbstractParser_h
+#include "AbstractParser.h"
+#endif
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+namespace rude{
+namespace config{
+
+class ParserJuly2004: public AbstractParser
+{
+	
+protected:
+
+	void stripTrailing(std::string&);
+	inline bool isEOL(char c);
+	inline bool chompEOL(std::istream& inputstream);
+	
+public:
+	
+	bool parse(std::istream& inputstream, AbstractOrganiser& organiser);
+
+};
+
+}} // end namespaces
+
+#endif
+
diff --git a/rudeconfig/src/RealOrganiser.cpp b/rudeconfig/src/RealOrganiser.cpp
new file mode 100644
index 0000000..5691422
--- /dev/null
+++ b/rudeconfig/src/RealOrganiser.cpp
@@ -0,0 +1,88 @@
+// RealOrganiser.cc
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "RealOrganiser.h"
+
+#ifndef INCLUDED_File_H
+#include "File.h"
+#endif
+
+#ifndef INCLUDED_Section_H
+#include "Section.h"
+#endif
+
+using namespace std;
+
+namespace rude{
+namespace config{
+
+RealOrganiser::RealOrganiser(File *file)
+{
+	d_file = file;
+	d_section = d_file->getSection("");
+}
+
+void RealOrganiser::foundSection(const char *sectionName, const char *comment)
+{
+	d_section = d_file->getSection(sectionName);
+	d_section->setSectionComment(comment);
+}
+	
+void RealOrganiser::foundComment(const char *comment)
+{
+	d_section->addComment(comment);
+}
+
+void RealOrganiser::foundWhiteSpace(const char *whitespace)
+{
+	d_section->addWhiteSpace(whitespace);
+}
+	
+void RealOrganiser::foundData(const char *key, const char *value, const char *comment)
+{
+	d_section->setValue(key, value, comment);
+}
+
+void RealOrganiser::foundSourceDest(const char *srcApp, const char *srcObj, const char *destApp, const char *destObj,
+		const char *width, const char *commType, const char *procMethod, const char *comment)
+{
+
+  /*
+  std::cout << "foundSourceDest srcApp " << srcApp
+            << " srcObj " << srcObj 
+            << " destApp " << destApp 
+            << " destObj " << destObj
+            << " width " << width 
+            << " commType " << commType
+            << " procMethod " << procMethod
+            << " comment " << comment << "\n";
+
+  */
+
+  d_section->addSourceDest(srcApp,srcObj,destApp,destObj,width,commType, procMethod, comment);
+}
+
+}} // end namespaces
+
diff --git a/rudeconfig/src/RealOrganiser.h b/rudeconfig/src/RealOrganiser.h
new file mode 100644
index 0000000..5165ea4
--- /dev/null
+++ b/rudeconfig/src/RealOrganiser.h
@@ -0,0 +1,63 @@
+// RealOrganiser.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+

+#ifndef INPUT_RealOrganiser_h
+#define INPUT_RealOrganiser_h
+

+#include "AbstractOrganiser.h"
+

+#include <string>
+

+namespace rude{
+namespace config{
+

+class File;
+class Section;
+

+class RealOrganiser: public AbstractOrganiser
+{
+	File *d_file;
+	Section *d_section;
+	
+public:
+

+	RealOrganiser(File*);
+

+	virtual void foundSection(const char *sectionName, const char *comment);
+	virtual void foundComment(const char *comment);
+	virtual void foundWhiteSpace(const char *whitespace);
+	virtual void foundData(const char *key, const char *value, const char *comment);
+	/* remedius
+	 * two more parameters: commType and procMethod were added due to the runtime opportunity
+     * of choosing communication type and pre-/post-processing method.
+     */
+	virtual void foundSourceDest(const char *srcApp, const char *srcObj, const char *destApp, const char *destObj,
+			const char *width, const char *commType, const char *procMethod, const char *comment);
+	
+

+};
+

+}} // end namespaces
+

+#endif
+

diff --git a/rudeconfig/src/Section.cpp b/rudeconfig/src/Section.cpp
new file mode 100644
index 0000000..a4baba3
--- /dev/null
+++ b/rudeconfig/src/Section.cpp
@@ -0,0 +1,415 @@
+// Section.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "Section.h"
+
+#ifndef INCLUDED_RUDE_DataLine_H
+#include "DataLine.h"
+#endif
+
+#ifndef INCLUDED_KeyValue_H
+#include "KeyValue.h"
+#endif
+
+#ifndef INCLUDED_SourceDest_H
+#include "SourceDest.h"
+#endif
+
+#ifndef INCLUDED_WhiteSpace_H
+#include "WhiteSpace.h"
+#endif
+
+#ifndef INCLUDED_Comment_H
+#include "Comment.h"
+#endif
+
+#ifndef INCLUDED_AbstractWriter_H
+#include "AbstractWriter.h"
+#endif
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+
+using namespace rude::config;
+
+namespace rude{
+  namespace config{
+
+    Section::Section(const char *sectionname, const char *sectioncomment)
+    {
+      d_isDeleted = false;
+      d_sectionname = sectionname ? sectionname: "";
+      d_sectioncomment = sectioncomment ? sectioncomment: "";
+    }
+
+    Section::~Section()
+    {
+      std::vector<DataLine*>::iterator iter;
+      for(iter = d_allDataVector.begin(); iter != d_allDataVector.end(); iter++)
+	{
+          delete (*iter);
+	}
+    }
+
+    void Section::acceptWriter(AbstractWriter& writer) const
+    {
+      writer.visitSection(*this);
+
+      // Send the writer to all the children.
+      // The writer will know what to do.
+      //
+      std::vector<DataLine*>::iterator iter;
+      for(iter = d_allDataVector.begin(); iter != d_allDataVector.end(); iter++)
+	{
+          (*iter)->acceptWriter(writer);
+	}
+    }
+
+    const char *Section::getSectionName() const
+    {
+      return d_sectionname.c_str();
+    }
+
+    const char *Section::getSectionComment() const
+    {
+      return d_sectioncomment.c_str();
+    }
+
+    void Section::setSectionComment(const char * newcomment)
+    {
+      d_sectioncomment = newcomment ? newcomment : "";
+    }
+
+    bool Section::isDeleted() const
+    {
+      return d_isDeleted;
+    }
+
+    void Section::isDeleted(bool is_it_or_not)
+    {
+      d_isDeleted = is_it_or_not;
+      if(d_isDeleted)
+	{
+          // Delete all data members
+          //
+          std::vector<DataLine*>::iterator iter;
+          for(iter = d_allDataVector.begin(); iter != d_allDataVector.end(); iter++)
+            {
+              (*iter)->isDeleted(true);
+            }
+          d_kv_vector.clear();
+          d_kv_map.clear();
+          d_sd_vector.clear();
+	}
+    }
+
+    int Section::getNumDataMembers() const
+    {
+	
+      return d_kv_vector.size();
+    }
+
+
+    int Section::getNumSourceDestMembers() const
+    {
+      return d_sd_vector.size();
+    }
+
+    const char *Section::getDataNameAt(int index) const
+    {
+      KeyValue *kv = d_kv_vector[index];
+      if(kv)
+	{
+          return kv->getName();
+	}
+      return "";
+    }
+
+    const char *Section::getDestAppAt(int index) const
+    {
+      SourceDest *sd = d_sd_vector[index];
+      if(sd)
+	{
+          return sd->getDestApp();
+	}
+      return "";
+    }
+
+    const char *Section::getSrcAppAt(int index) const
+    {
+      SourceDest *sd = d_sd_vector[index];
+      if(sd)
+	{
+          return sd->getSrcApp();
+	}
+      return "";
+    }
+    const char *Section::getDestObjAt(int index) const
+    {
+      SourceDest *sd = d_sd_vector[index];
+      if(sd)
+	{
+          return sd->getDestObj();
+	}
+      return "";
+    }
+
+    const char *Section::getSrcObjAt(int index) const
+    {
+      SourceDest *sd = d_sd_vector[index];
+      if(sd)
+	{
+          return sd->getSrcObj();
+	}
+      return "";
+    }
+
+    // Returns the concatenation of srcApp.srcObj
+    const char *Section::getWidthAt(int index) const
+    {
+      SourceDest *sd = d_sd_vector[index];
+      if(sd)
+	{
+          return sd->getWidth();
+	}
+      return "";
+    }
+    const char *Section::getCommTypeAt(int index) const
+    {
+    	SourceDest *sd = d_sd_vector[index];
+    	if(sd)
+    	{
+    		return sd->getCommType();
+    	}
+    	return "";
+
+    }
+    const char *Section::getProcMethodAt(int index) const
+    {
+    	SourceDest *sd = d_sd_vector[index];
+    	if(sd)
+    	{
+    		return sd->getProcMethod();
+    	}
+    	return "";
+    }
+    const char *Section::getDataValueAt(int index) const
+    {
+      KeyValue *kv = d_kv_vector[index];
+      if(kv)
+	{
+          return kv->getValue();
+	}
+      return "";
+    }
+
+    // MAPPED
+    //
+    bool Section::exists(const char *name) const
+    {
+      if(name)
+	{
+          std::string myname = name;
+          KeyValue *mydata = d_kv_map[myname];
+          if(mydata)
+            {
+              return true;
+            }	
+	}
+      return false;
+    }
+
+    // MAPPED
+    //
+    const char * Section::getValue(const char *name) const
+    {
+      if(name)
+	{
+          std::string myname=name;
+          KeyValue *mydata = d_kv_map[myname];
+          if(mydata)
+            {
+              return mydata->getValue();
+            }
+	}
+      return "";
+    }
+
+    // MAPPED
+    //
+    void Section::setValue(const char *name, const char *value)
+    {
+      if(name)
+	{
+          std::string myname=name;
+          KeyValue *mydata = d_kv_map[myname];
+          if(mydata)
+            {
+              mydata->setValue(value);
+              mydata->isDeleted(false);
+			
+            } 
+          else
+            {	
+              KeyValue *newdata = new KeyValue();
+              newdata->setName(name);
+              newdata->setValue(value);
+              d_allDataVector.push_back(newdata);
+              d_kv_vector.push_back(newdata);
+              d_kv_map[myname] = newdata;
+            }
+	}
+    }
+
+    // MAPPED
+    //
+    const char * Section::getComment(const char *name) const
+    {
+      if(name)
+	{
+          std::string myname=name;
+          KeyValue *mydata = d_kv_map[myname];
+          if(mydata)
+            {
+              return mydata->getComment();
+            }
+	}
+      return "";
+    }
+
+    // MAPPED
+    //
+    void Section::setComment(const char *name, const char *comment)
+    {
+      if(name)
+	{
+          std::string myname=name;
+          KeyValue *mydata = d_kv_map[myname];
+          if(mydata)
+            {
+              mydata->setComment(comment);
+            } 
+	}
+    }
+
+    // MAPPED
+    //
+    void Section::setValue(const char *name, const char *value, const char *comment)
+    {
+	
+      if(name)
+	{
+          std::string myname=name;
+          KeyValue *mydata = d_kv_map[myname];
+          if(mydata)
+            {
+              mydata->setValue(value);
+              mydata->setComment(comment);
+              mydata->isDeleted(false);
+            } 
+          else
+            {	
+              KeyValue *newdata = new KeyValue(name, value, comment);
+
+              d_allDataVector.push_back(newdata);
+              d_kv_vector.push_back(newdata);
+              d_kv_map[myname] = newdata;
+            }
+	}
+    }
+
+    // CREATES
+    //
+    void Section::addSourceDest(const char *srcApp, const char *srcObj, const char *destApp, const char *destObj,
+    		const char *width, const char *commType, const char *procMethod, const char *comment)
+    {
+	
+      SourceDest *newsd = new SourceDest(srcApp, srcObj, destApp, destObj, width, commType, procMethod, comment);
+
+      d_allDataVector.push_back(newsd);
+      d_sd_vector.push_back(newsd);
+
+    }
+  
+
+    // MAPPED
+    //
+    void Section::addComment(const char *comment)
+    {
+      Comment *newdata = new Comment(comment);
+      d_allDataVector.push_back(newdata);
+    }
+
+    // MAPPED
+    //
+    void Section::addWhiteSpace(const char *whitespace)
+    {
+      WhiteSpace *newdata = new WhiteSpace(whitespace);
+      d_allDataVector.push_back(newdata);
+    }
+
+    // MAPPED
+    //
+    bool Section::deleteData(const char *name)
+    {
+      // Since we are keeping deleted data in the d_allDataVector,
+      // multiple set/deletes will require lots of memory!!
+      //
+      if(name)
+	{
+          std::string myname=name;
+          KeyValue *mydata = d_kv_map[myname];
+          if(mydata)
+            {
+              // Remain in d_allDataVector, but as deleted
+              //
+              mydata->isDeleted(true);
+
+              // remove from keyvalue vector and map
+              //
+              std::vector<KeyValue*>::iterator iter;
+              for(iter = d_kv_vector.begin(); iter != d_kv_vector.end(); iter ++)
+                {
+                  if( *iter == mydata )
+                    {
+                      d_kv_vector.erase(iter);
+                      break;
+                    }
+                }
+			
+              d_kv_map.erase(myname);
+
+              return true;
+            }
+	}
+      return false;
+    }
+
+  }} // end namespace rude::config
+
+
diff --git a/rudeconfig/src/Section.h b/rudeconfig/src/Section.h
new file mode 100644
index 0000000..94a18e5
--- /dev/null
+++ b/rudeconfig/src/Section.h
@@ -0,0 +1,262 @@
+// Section.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#ifndef INCLUDED_Section_H
+#define INCLUDED_Section_H
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+#ifndef INCLUDED_VECTOR
+#include <vector>
+#define INCLUDED_VECTOR
+#endif
+
+#ifndef INCLUDED_MAP
+#include <map>
+#define INCLUDED_MAP
+#endif
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+namespace rude{
+  namespace config{
+
+    class DataLine;
+    class KeyValue;
+    class AbstractWriter;
+    class SourceDest;
+
+    //=
+    // Section represents a single section within a configuration file.
+    // It is identified by its section name, which can include whitespace, 
+    // and manages the set of all data and/or comments associated with that section.
+    // 
+    // Each piece of data is identified by its name.  Currently, only one piece of data
+    // is recognized for any given name.  In the case where two or more values exist for the
+    // same name (within a section), only the last value is recognized - any previous values are discarded.
+    //=
+    class Section{
+
+      bool d_isDeleted;
+      std::string d_sectionname;
+      std::string d_sectioncomment;
+
+      // Q: Should these really be mutable???
+      mutable std::vector<DataLine*> d_allDataVector;
+      mutable std::vector<KeyValue*> d_kv_vector;
+      mutable std::map<std::string, KeyValue*> d_kv_map;
+
+      // Note that a source can have multiple dest,
+      // but a dest can only have one source.
+      // Therefor we use dest for lookups!
+      mutable std::vector<SourceDest*> d_sd_vector;
+
+    public:
+
+      Section(const char *sectionname, const char *sectioncomment=0);
+      void acceptWriter(AbstractWriter& writer) const;
+
+      //=
+      // Writes the section and all associated data to the outputstream
+      //
+      // <b>If the section is marked as deleted:</b>
+      // The entire section is commented out.  This means that it is still printed out,
+      // but each line is begun with the comment character.  If the comment character is
+      // set to null, then the section is not printed out at all - it is essentially discarded.
+      //
+      // In normal circumstances, the '=' is the most appropriate delimiter to use.
+      // If delimiter is null, then whie
+      //=
+      void write(std::ostream& outputstream, char commentchar, char delimiter, bool preserveDeleted);
+	
+      //=
+      // Returns this section's name, identified by [somename] in the config/ini file
+      //=
+      const char *getSectionName() const;
+
+
+      //=
+      // Returns the section-comment (found after the section name)
+      // 
+      // An example of a section-comment is:
+      //
+      // [Dogs]  # this section is about dogs
+      //
+      //=
+      const char *getSectionComment() const;
+
+
+      //=
+      // Sets the section comment (found after the section name)
+      //=
+      void setSectionComment(const char *newcomment);
+
+
+      //=
+      // Returns whether or not this section is flagged as deleted...
+      //=
+      bool isDeleted() const;
+
+
+      //=
+      // (Un)marks this section as deleted
+      // When marked as deleted, all data members are marked as deleted
+      // When undeleted, data members remain marked as deleted....
+      //=
+      void isDeleted(bool is_it_or_not);
+
+
+      //=
+      // Returns the number of (non-deleted) data members
+      // Deleted data, comments and blank lines are not included in the count.
+      //=
+      int getNumDataMembers() const;
+
+
+      //=
+      // # SourceDest objects
+      //=
+      int getNumSourceDestMembers() const;
+
+
+      //=
+      // Returns the name of the (undeleted) data member at the specified index
+      // Returns NULL if the index is out of range
+      //=
+      const char *getDataNameAt(int index) const;
+
+      const char *getDestAppAt(int index) const;
+      const char *getSrcAppAt(int index) const;
+      const char *getDestObjAt(int index) const;
+      const char *getSrcObjAt(int index) const;
+
+      const char *getWidthAt(int index) const;
+
+      /* remedius
+       * returns <collective>, <point-to-point> or "" type of communication.
+       */
+      const char *getCommTypeAt(int index) const;
+      /* remedius
+       * returns <tree>, <table> or  "" processing method.
+       */
+      const char *getProcMethodAt(int index) const;
+
+
+      //=
+      // Returns the name of the (undeleted) data member at the specified index
+      // Returns NULL if the index is out of range
+      //=
+      const char *getDataValueAt(int index) const;
+
+
+      //=
+      // Returns true if data name exists (and is not marked as deleted), false otherwise
+      //=
+      bool exists(const char *name) const;
+
+      //=
+      // Returns the value associated with the data identified by <i>name</i>
+      // Returns NULL if data name does not exist (or is marked as deleted)
+      //=
+      const char *getValue(const char *name) const;
+
+
+      //=
+      // Returns the comment associated with the data identified by <i>name</i>
+      // Returns NULL if data name does not exist (or is marked as deleted)
+      //=
+      const char *getComment(const char *name) const;
+
+	
+      //=
+      // Sets the <b>value</b> for the data member identified by <i>name</i>
+      // If a data member already exists with the given <i>name</i>, then the value is replaced. 
+      // Otherwise a new data item is created..
+      // If the data item already exists, but has been marked as deleted,
+      // it will be revived (unmarked) and its value updated.
+      // Existing comments associated with the data member are not altered.
+      //=
+      void setValue(const char *name, const char *value);
+
+
+      //=
+      // Replaces the comment for the data member identified by <i>name</i>
+      // Sets the comment whether or not the data is marked as deleted.
+      // If the data identified by <i>name</i> does not exist, then nothing happens
+      //=
+      void setComment(const char *name, const char *comment);
+
+	
+      //=
+      // Sets the <b>value</b> and the <b>comment</b> for the data member identified by <i>name</i>
+      // If a data member already exists with the given <i>name</i>, then the value is replaced. 
+      // Otherwise a new data item is created..
+      // If the data item already exists, but has been marked as deleted,
+      // it will be revived (unmarked) and updated.
+      //=
+      void setValue(const char *name, const char *value, const char *comment);
+
+      /* remedius
+       * two more parameters: commType and procMethod were added due to the runtime opportunity
+       * of choosing communication type and pre-/post-processing method.
+       */
+      void addSourceDest(const char *srcApp, const char *srcObj, const char *destApp, const char *destObj,
+    		  const char *width, const char *commType, const char *procMethod, const char *comment);
+
+
+      //=
+      // Adds a comment line to the end of the section
+      //=	
+      void addComment(const char *comment);
+	
+      //=
+      // Adds whitespace line to the end of the section
+      //=	
+      void addWhiteSpace(const char *whitespace);
+
+      //=
+      // Marks the data identified by name as deleted
+      // Returns false if data does not exist within this 
+      // section (or has already been marked as deleted)
+      //=
+      bool deleteData(const char *name);
+
+
+      ~Section();
+	
+    };
+  }} // end namespace rude::config
+#endif
+
diff --git a/rudeconfig/src/SourceDest.cpp b/rudeconfig/src/SourceDest.cpp
new file mode 100644
index 0000000..7661932
--- /dev/null
+++ b/rudeconfig/src/SourceDest.cpp
@@ -0,0 +1,154 @@
+//
+// SourceDest.cpp
+//
+// Written by Johannes Hjorth, based on original KeyValue.cpp
+// by Matthew Flood.
+//
+
+#include "../config.h"
+
+#include "SourceDest.h"
+
+#ifndef INCLUDED_AbstractWriter_H
+#include "AbstractWriter.h"
+#endif
+
+#ifndef INCLUDED_CSTDIO
+#include <cstdio>
+#define INCLUDED_CSTDIO
+#endif
+
+using namespace std;
+namespace rude{
+namespace config{
+
+SourceDest::SourceDest()
+{
+	d_srcApp = "";
+	d_srcObj = "";
+	d_destApp = "";
+	d_destObj = "";
+	d_width = "";
+	d_comment = "";
+	d_commType = "";
+	d_procMethod = "";
+}
+
+SourceDest::SourceDest(const char *srcApp, const char *srcObj, const char *destApp,  const char *destObj,
+		const char *width,const char* commType, const char *procMethod, const char *comment)
+{
+	d_srcApp  = srcApp  ? srcApp  : "";
+	d_srcObj  = srcObj  ? srcObj  : "";
+	d_destApp = destApp ? destApp : "";
+	d_destObj = destObj ? destObj : "";
+	d_width   = width   ? width   : "";
+	d_comment = comment ? comment : "";
+	d_commType = commType ? commType : "";
+	d_procMethod = procMethod ? procMethod : "";
+}
+
+void SourceDest::acceptWriter(AbstractWriter& writer) const
+{
+  std::cout << "writer.visitSourceDest not implemented yet!";
+  std::cout << "\nsrcApp: \"" << d_srcApp << "\", srcObj: \"" << d_srcObj << "\"";
+  std::cout << "\ndestApp: \"" << d_srcApp << "\", destObj: \"" << d_srcObj << "\"";
+  std::cout << "\nwidth: " << d_width;
+  std::cout << "\ncommType: " << d_commType;
+  std::cout << "\nprocMethod: " << d_procMethod;
+  std::cout << "\ncomment: \"" << d_comment << "\"\n";
+  //writer.visitKeyValue(*this);
+}
+
+std::string SourceDest::toString()
+{
+  std::cout << "REMOVE THIS FUNCTION";
+
+  return   "\nsrcApp: \"" + d_srcApp + "\", srcObj: \"" + d_srcObj + "\"" 
+           + "\ndestApp: \"" + d_destApp + "\", destObj: \"" + d_destObj + "\""
+           + "\nwidth: " + d_width
+           + "\ncommType: " + d_commType
+           + "\nprocMethod: " + d_procMethod
+           + "\ncomment: \"" + d_comment + "\"\n";
+}
+
+
+const char *SourceDest::getSrcApp() const
+{
+	return d_srcApp.c_str();
+}
+
+const char *SourceDest::getSrcObj() const
+{
+	return d_srcObj.c_str();
+}
+
+const char *SourceDest::getDestApp() const
+{
+	return d_destApp.c_str();
+}
+
+const char *SourceDest::getDestObj() const
+{
+	return d_destObj.c_str();
+}
+
+const char *SourceDest::getWidth() const
+{
+	return d_width.c_str();
+}
+const char *SourceDest::getCommType() const
+{
+	return d_commType.c_str();
+}
+const char *SourceDest::getProcMethod() const
+{
+	return d_procMethod.c_str();
+}
+const char *SourceDest::getComment() const
+{
+	return d_comment.c_str();
+}
+
+void SourceDest::setSrcApp(const char *srcApp)
+{
+	d_srcApp = srcApp ? srcApp : "";
+}
+
+void SourceDest::setSrcObj(const char *srcObj)
+{
+	d_srcObj = srcObj ? srcObj : "";
+}
+
+void SourceDest::setDestApp(const char *destApp)
+{
+	d_destApp = destApp ? destApp : "";
+}
+
+void SourceDest::setDestObj(const char *destObj)
+{
+	d_destObj = destObj ? destObj : "";
+}
+
+void SourceDest::setWidth(const char *width)
+{
+	d_width = width ? width : "";
+}
+void SourceDest::setCommType(const char *commType)
+{
+	d_commType = commType ? commType : "";
+}
+void SourceDest::setProcMethod(const char *procMethod)
+{
+	d_procMethod = procMethod ? procMethod : "";
+}
+void SourceDest::setComment(const char *comment)
+{
+	d_comment = comment ? comment : "";
+}
+
+SourceDest::~SourceDest()
+{
+
+}
+}} // end namespace rude::config
+
diff --git a/rudeconfig/src/SourceDest.h b/rudeconfig/src/SourceDest.h
new file mode 100644
index 0000000..bbcac31
--- /dev/null
+++ b/rudeconfig/src/SourceDest.h
@@ -0,0 +1,126 @@
+// SourceDest.h
+//
+// Added by Johannes Hjorth, 2008
+// 
+// Feel free to use the code, have fun!
+//
+// Based on the KeyValue-code
+
+
+
+
+#ifndef INCLUDED_SourceDest_H
+#define INCLUDED_SourceDest_H
+
+#ifndef INCLUDED_DataLine_H
+#include "DataLine.h"
+#endif
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+namespace rude{
+namespace config{
+//=
+// SourceDest represents message passing from Source to Dest
+// 
+// app1.source -> dest
+// dest <- app2.source
+// app2.dest <- source
+//
+
+class SourceDest: public DataLine{
+
+
+	std::string d_srcApp;
+	std::string d_srcObj;
+	std::string d_destApp;
+	std::string d_destObj;
+	std::string d_width;
+	std::string d_comment;
+	/* remedius
+	 * <collective> or <point-to-point>
+	 */
+	std::string d_commType;
+	/* remedius
+	 * <tree> or <table>
+	*/
+	std::string d_procMethod;
+
+public:
+
+	// default constructor
+	SourceDest();
+	/* remedius
+	 * two more parameters: commType and procMethod were added due to the runtime opportunity
+	 * of choosing communication type and pre-/post-processing method.
+	 */
+	SourceDest(const char *srcApp, const char *srcObj, const char *destApp,  const char *destObj,
+			const char *width, const char* commType, const char *procMethod, const char *comment);
+	
+	void acceptWriter(AbstractWriter& writer) const;
+        std::string toString();
+
+        //
+	const char *getSrcApp() const;
+	const char *getSrcObj() const;
+	const char *getDestApp() const;
+	const char *getDestObj() const;
+	const char *getWidth() const;
+    /* remedius
+     *
+     */
+	const char *getCommType() const;
+	/* remedius
+	 *
+	 */
+	const char *getProcMethod() const;
+
+	//= 
+	// Returns the comment associated with the data member
+	// Will return the comment even if the data member is flagged as being deleted
+	// Always returns at least the empty string, will never return null.
+	//=
+	const char *getComment() const;
+
+	//= 
+	// Sets the name of the data member
+	// Will set the name even if the data member is flagged as being deleted or a comment
+	// Accepts null
+	//=
+	void setSrcApp(const char *name);
+	void setSrcObj(const char *name);
+	void setDestApp(const char *name);
+	void setDestObj(const char *name);
+	void setWidth(const char *name);
+	/* remedius
+	 *
+	 */
+	void setCommType(const char *commType);
+	/* remedius
+	 *
+	 */
+	void setProcMethod(const char *procMethod);
+
+	//= 
+	// Sets the comment associated with the data member
+	// Will set the comment even if the data member is flagged as being deleted
+	// Accepts null
+	//=
+	void setComment(const char *comment);
+	
+	~SourceDest();
+	
+};
+
+}} // end namespace rude::config
+
+#endif
+
diff --git a/rudeconfig/src/WhiteSpace.cpp b/rudeconfig/src/WhiteSpace.cpp
new file mode 100644
index 0000000..bc97dc8
--- /dev/null
+++ b/rudeconfig/src/WhiteSpace.cpp
@@ -0,0 +1,58 @@
+// WhiteSpace.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#include "../config.h"
+
+#include "WhiteSpace.h"
+
+#ifndef INCLUDED_AbstractWriter_H
+#include "AbstractWriter.h"
+#endif
+
+#ifndef INCLUDED_CSTDIO
+#include <cstdio>
+#define INCLUDED_CSTDIO
+#endif
+
+using namespace std;
+namespace rude{
+namespace config{
+
+WhiteSpace::WhiteSpace(const char *whitespace)
+{
+	d_whitespace = whitespace ? whitespace : "";
+}
+
+void WhiteSpace::acceptWriter(AbstractWriter& writer) const
+{
+	writer.visitWhiteSpace(*this);
+}
+
+const char *WhiteSpace::getWhiteSpace() const
+{
+	return d_whitespace.c_str();
+}
+
+}} // end namespace rude::config
+
diff --git a/rudeconfig/src/WhiteSpace.h b/rudeconfig/src/WhiteSpace.h
new file mode 100644
index 0000000..2131df5
--- /dev/null
+++ b/rudeconfig/src/WhiteSpace.h
@@ -0,0 +1,57 @@
+// WhiteSpace.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#ifndef INCLUDED_WhiteSpace_H
+#define INCLUDED_WhiteSpace_H
+
+#ifndef INCLUDED_DataLine_H
+#include "DataLine.h"
+#endif
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+namespace rude{
+namespace config{
+
+class WhiteSpace: public DataLine{
+
+	std::string d_whitespace;
+
+public:
+
+	WhiteSpace(const char *WhiteSpace);
+	
+	void acceptWriter(AbstractWriter& writer) const;
+
+	const char *getWhiteSpace() const;
+	
+};
+
+}} // end namespace rude::config
+
+#endif
+
diff --git a/rudeconfig/src/Writer.cpp b/rudeconfig/src/Writer.cpp
new file mode 100644
index 0000000..71bce56
--- /dev/null
+++ b/rudeconfig/src/Writer.cpp
@@ -0,0 +1,387 @@
+// Writer.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "Writer.h"
+
+#ifndef INCLUDED_File_H
+#include "File.h"
+#endif
+
+#ifndef INCLUDED_Section_H
+#include "Section.h"
+#endif
+
+#ifndef INCLUDED_KeyValue_H
+#include "KeyValue.h"
+#endif
+
+#ifndef INCLUDED_Comment_H
+#include "Comment.h"
+#endif
+
+#ifndef INCLUDED_WhiteSpace_H
+#include "WhiteSpace.h"
+#endif
+
+#ifndef INCLUDED_CSTDLIB
+#include <cstdlib>
+#define INCLUDED_CSTDLIB
+#endif
+
+#ifndef INCLUDED_CCTYPE
+#include <cctype>
+#define INCLUDED_CCTYPE
+#endif
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+using namespace std;
+
+namespace rude{
+namespace config{
+
+
+Writer::Writer()
+{
+
+}
+
+Writer::~Writer()
+{
+
+}
+
+
+void Writer::visitFile(const File& configfile) const
+{
+
+}
+
+void Writer::visitSection(const Section& configsection) const
+{
+		std::string name = configsection.getSectionName();
+		
+		// if there is a section name, we print it out [between brackets]
+		//
+		if(name != "")
+		{
+			if( configsection.isDeleted() )
+			{
+				if ( d_commentchar && d_preservedeleted )
+				{
+					*d_outputstream << d_commentchar << " ";
+				}
+				else
+				{
+					return;
+				}
+			}
+		
+			int position = 0;
+			size_t location;
+
+			// escape all backslashes
+			//
+			while( (location = name.find("\\", position)) != string::npos )
+			{
+				// location points right at the '\'
+				name.insert(location,  "\\");
+				position = (int) location + 2;
+			}
+
+			// escape all ']''s
+			//
+			while( (location = name.find("]", position)) != string::npos )
+			{
+				// location points right at the ']'
+				name.insert(location,  "\\");
+				position = (int) location + 2;
+			}
+			
+			*d_outputstream << "[" << name << "]";
+			
+			// If the section name has a comment, we print it out after the section name
+			//
+			if(configsection.getSectionComment()[0] != 0 && d_commentchar)
+			{
+				*d_outputstream << "\t" << d_commentchar << configsection.getSectionComment();
+			}
+
+			// newline ends the section header
+			//
+			*d_outputstream << "\n";
+		}
+}
+
+void Writer::visitComment(const Comment& comment) const
+{
+	if(d_preservecomments && d_commentchar && ( !comment.isDeleted() || d_preservedeleted ))
+	{
+			*d_outputstream << d_commentchar << comment.getComment() << "\n";
+	}
+}
+
+void Writer::visitWhiteSpace(const WhiteSpace& whitespace) const
+{
+	if(d_preservewhitespace && ( !whitespace.isDeleted() || d_preservedeleted ))
+	{
+			*d_outputstream << whitespace.getWhiteSpace();
+	}
+}
+
+
+void Writer::visitKeyValue(const KeyValue& dataline) const
+{
+	if(dataline.isDeleted() && ( !d_commentchar || !d_preservedeleted))
+	{
+		// Don't preserve deleted data when comments are null
+		// or we don't want to preserve them
+		return;
+	}
+	else
+	{
+		string key = dataline.getName();
+		string value = dataline.getValue();
+		string comment = dataline.getComment();
+
+		string commentchar(1,d_commentchar);
+		
+
+		if(dataline.isDeleted())
+		{
+			// print the comment character
+			//
+			*d_outputstream << d_commentchar << " ";
+		}
+
+		if(key != "")
+		{
+
+
+			int position = 0;
+			size_t location;
+
+			// escape all backslashes
+			//
+			while( (location = key.find("\\", position)) != string::npos )
+			{
+				// location points right at the '\'
+				key.insert(location,  "\\");
+				position = (int) location + 2;
+			}
+
+
+			// escape comment characters
+			// unless the comment character is a backslash, which we've already escaped....
+			//
+			if(d_commentchar && d_commentchar != '\\')
+			{
+				position = 0;
+
+				while( (location = key.find(commentchar, position)) != string::npos )
+				{
+					// location points right at the '"'
+					key.insert(location,  "\\");
+					position = (int) location + 2;
+				}
+			}
+
+			// escape all delimiters, unless the delimiter is a backslash or the same as the comment, god forbid.
+			//
+			//
+			if(d_delimiter != '\\' && d_delimiter != d_commentchar)
+			{
+				if(d_delimiter)
+				{
+					string delimiter(1, d_delimiter);
+					position = 0;
+
+					while( (location = key.find(delimiter, position)) != string::npos )
+					{
+						// location points right at the '"'
+						key.insert(location,  "\\");
+						position = (int) location + 2;
+					}
+				}
+				else
+				{
+					position = 0;
+
+					while( (location = key.find("\t", position)) != string::npos )
+					{
+						// location points right at the '"'
+						key.insert(location,  "\\");
+						position = (int) location + 2;
+					}
+					
+					position = 0;
+
+					while( (location = key.find(" ", position)) != string::npos )
+					{
+						// location points right at the '"'
+						key.insert(location,  "\\");
+						position = (int) location + 2;
+					}					
+
+				}				
+			}
+
+			// print the key
+			//
+			*d_outputstream << key;
+		}
+
+		if(value != "")
+		{
+			// print out the delimiter
+			//
+			*d_outputstream  << " " << ( d_delimiter ? d_delimiter : '\t' ) << " ";
+
+			int position = 0;
+			size_t location;
+
+			// escape all backslashes
+			//
+			string backslash(1,'\\');
+
+			while( (location = value.find("\\", position)) != string::npos )
+			{
+				// location points right at the '\'
+				value.insert(location,  "\\");
+				position = (int) location + 2;
+			}
+
+			// escape all quotes
+			//
+			string quote(1,'"');
+			position = 0;
+
+			while( (location = value.find("\"", position)) != string::npos )
+			{
+				// location points right at the '"'
+				value.insert(location,  "\\");
+				position = (int) location + 2;
+			}
+
+			// escape comment characters
+			// unless the comment character is a backslash or a quote, which we've already escaped....
+			//
+			if(d_commentchar && d_commentchar != '\\' && d_commentchar != '"')
+			{
+				position = 0;
+
+				while( (location = value.find(commentchar, position)) != string::npos )
+				{
+					// location points right at the '"'
+					value.insert(location,  "\\");
+					position = (int) location + 2;
+				}
+			}
+
+
+
+
+
+			// if value starts with whitespace, ends with whitespace or contains the comment character or CRLF's, quote the value, 
+			//
+			int size = value.size();
+
+			if(		isspace(value[0]) || 
+						isspace(value[size-1]) || 
+						(value.find("\r", 0) != string::npos) || 
+						(value.find("\f", 0) != string::npos) || 
+						(value.find("\n", 0)!= string::npos) 
+			)
+			{
+
+
+				value.insert(0, "\"");
+				value += "\"";
+			}
+
+			// if data is deleted and there are CRLFS
+			// then each line must start with a comment character.
+			// The safest way is just to follow every newline character with a comment
+			//
+			if(		dataline.isDeleted() && ( 
+						(value.find("\r", 0) != string::npos) || 
+						(value.find("\f", 0) != string::npos) || 
+						(value.find("\n", 0)!= string::npos) )
+			  )
+			{	
+				position = 0;				
+
+				while( (location = value.find("\r", position)) != string::npos )
+				{
+					// location points right at the '"'
+					value.insert(location + 1,  commentchar);
+					position = (int) location + 2;
+				}
+				position = 0;				
+				while( (location = value.find("\f", position)) != string::npos )
+				{
+					// location points right at the '"'
+					value.insert(location + 1,  commentchar);
+					position = (int) location + 2;
+				}
+
+				position = 0;				
+				while( (location = value.find("\n", position)) != string::npos )
+				{
+					// location points right at the '"'
+					value.insert(location + 1,  commentchar);
+					position = (int) location + 2;
+				}
+			}			
+
+			*d_outputstream << value;
+
+		}
+
+		if( comment != "" && d_commentchar && d_preservecomments)
+		{
+			// add value's comment at end if it exists
+			// and there is a comment character
+			//
+					*d_outputstream << "\t " << d_commentchar << comment;
+		}
+
+		// end the entry with a newline
+		//
+		*d_outputstream << "\n";
+	}
+}
+
+
+}} // end namespaces
+
diff --git a/rudeconfig/src/Writer.h b/rudeconfig/src/Writer.h
new file mode 100644
index 0000000..a8baedb
--- /dev/null
+++ b/rudeconfig/src/Writer.h
@@ -0,0 +1,106 @@
+// Writer.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#ifndef INCLUDED_Writer_H
+#define INCLUDED_Writer_H
+
+#include "AbstractWriter.h"
+#include <iostream>
+
+namespace rude{
+namespace config{
+
+class File;
+class Section;
+class KeyValue;
+class Comment;
+class WhiteSpace;
+
+
+class Writer: public AbstractWriter{
+
+public:
+
+	Writer();
+		
+	virtual void visitFile(const File& configfile) const;
+	virtual void visitSection(const Section& configsection) const;
+	virtual void visitKeyValue(const KeyValue& keyvalue) const;
+	virtual void visitComment(const Comment& comment) const;
+	virtual void visitWhiteSpace(const WhiteSpace& whitespace) const;
+
+	virtual ~Writer();
+
+	//=
+	// Writes the data member to an output stream
+	// 
+	// For the following specification examples, assume an object with the following properties:
+	// 
+	// <b>name</b> = "color"
+	// <b>value</b>="blue"
+	// <b>comment</b>="Color of the background"
+	// 
+	// <ul>
+	// <li>If comment char is null, comments/deleted items will not be written
+	// 
+	// <b>Example:</b> object->write(stdout, 0, "=")
+	// <b>Results:</b>
+	// <font color=red><code>color = blue</code></font>	 
+	// 
+	// <li>If delimiter is null, name / value will be separated by whitespace
+	// 
+	// <b>Example:</b> object->write(stdout, "#", 0)
+	// <b>Results:</b>
+	// <font color=red><code>color  blue  # Color of the background</code></font>	 
+	// 
+	// <li>Undefined results if outputstream is null
+	// 
+	// <b>Example:</b> object->write(0, "#", "=")
+	// <b>Results:</b>
+	// <font color=red><code>??????????</code></font>	 
+	// 
+	// <li>If the data member is a comment, then only the comment data is written - any values
+	// for the name / value are discarded.
+	// 
+	// <b>Example:</b> object->write(stdout, "#", "=")
+	// <b>Results:</b>
+	// <font color=red><code># Color of the background</code></font>	 
+	// 
+	// <li>If the data member has been (flagged as) deleted, then the name, value and original comment are preserved, 
+	// preceded by a comment character.
+	// 
+	// <b>Example:</b> object->write(stdout, "#", "=")
+	// <b>Results:</b>
+	// <font color=red><code># color = blue  # Color of the background</code></font>	 
+	// 
+	// </ul>
+	//=
+
+
+};
+
+}} // end namespaces
+
+#endif
+
diff --git a/rudeconfig/src/config.cpp b/rudeconfig/src/config.cpp
new file mode 100644
index 0000000..b3c3b23
--- /dev/null
+++ b/rudeconfig/src/config.cpp
@@ -0,0 +1,325 @@
+// config.cpp
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+#include "../config.h"
+
+#include "config.h"
+
+#ifndef INCLUDED_RUDE_CONFIGIMPL_H
+#include "ConfigImpl.h"
+#endif
+
+#ifndef INCLUDED_IOSTREAM
+#include <iostream>
+#define INCLUDED_IOSTREAM
+#endif
+
+#ifndef INCLUDED_STRING
+#include <string>
+#define INCLUDED_STRING
+#endif
+
+using namespace rude::config;
+
+namespace rude{
+
+//////////////////////////////////////////
+// STATIC Methods
+//////////////////////////////////////////
+
+const char *Config::version()
+{
+	static std::string ver="3.";
+	ver += ConfigImpl::version();
+	return ver.c_str();
+}
+	
+	void Config::setDefaultConfigFile(const char *filepath)
+	{
+		ConfigImpl::setDefaultConfigFile(filepath);
+	}
+
+	const char *Config::getDefaultConfigFile()
+	{
+		return ConfigImpl::getDefaultConfigFile();
+	}
+
+	void Config::setDefaultCommentCharacter(char c)
+	{
+		ConfigImpl::setDefaultCommentCharacter(c);
+	}
+
+	char Config::getDefaultCommentCharacter()
+	{
+		return ConfigImpl::getDefaultCommentCharacter();
+	}
+
+	void Config::setDefaultDelimiter(char c)
+	{
+		ConfigImpl::setDefaultDelimiter(c);
+	}
+
+	char Config::getDefaultDelimiter()
+	{
+		return ConfigImpl::getDefaultDelimiter();
+	}
+
+	void Config::setDefaultPreserveDeleted(bool shouldPreserve)
+	{
+		ConfigImpl::setDefaultPreserveDeleted(shouldPreserve);
+	}
+
+	bool Config::getDefaultPreserveDeleted()
+	{
+		return ConfigImpl::getDefaultPreserveDeleted();
+	}
+
+//////////////////////////////////////////
+// INSTANCE Methods
+//////////////////////////////////////////
+
+Config::Config()
+{
+	d_implementation = new ConfigImpl();
+}
+
+Config::~Config()
+{
+	delete d_implementation;
+	d_implementation = 0;
+}
+
+void Config::setConfigFile(const char *filepath)
+{
+	d_implementation->setConfigFile(filepath);
+}
+
+const char * Config::getConfigFile()
+{
+	return d_implementation->getConfigFile();
+}
+
+void Config::setCommentCharacter(char commentchar)
+{
+	d_implementation->setCommentCharacter(commentchar);
+}
+
+void Config::preserveDeletedData(bool shouldPreserve)
+{
+	d_implementation->preserveDeletedData(shouldPreserve);
+}
+
+void Config::setDelimiter(char delimiter)
+{
+	d_implementation->setDelimiter(delimiter);
+}
+
+bool Config::load()
+{
+	return d_implementation->load();
+}
+
+bool Config::load(const char *filename)
+{
+	return d_implementation->load(filename);
+}
+
+bool Config::load(std::istream& file)
+{
+	return d_implementation->load(file);
+}
+
+
+bool Config::save()
+{
+	return d_implementation->save();
+}
+
+bool Config::save(const char *filepath)
+{
+	return d_implementation->save(filepath);
+}
+
+
+void Config::clear()
+{
+	d_implementation->clear();
+}
+
+
+const char *Config::getError()
+{
+	return d_implementation->getError();
+}
+
+
+//////////////////////////////////////////
+// Section Methods
+//////////////////////////////////////////
+int Config::getNumSections() const
+{
+	return d_implementation->getNumSections();
+}
+
+const char *Config::getSectionNameAt(int index) const
+{
+	return d_implementation->getSectionNameAt(index);
+}
+
+bool Config::setSection(const char *sectionname, bool shouldCreate)
+{
+	return d_implementation->setSection(sectionname, shouldCreate);
+}
+
+bool Config::setSection(const char *sectionname)
+{
+	return d_implementation->setSection(sectionname, true);
+}
+
+bool Config::deleteSection(const char *sectionname)
+{
+	return d_implementation->deleteSection(sectionname);
+}
+
+//////////////////////////////////////////
+// Data Methods
+//////////////////////////////////////////
+
+
+int Config::getNumSourceDestMembers() const
+{
+  return d_implementation->getNumSourceDestMembers();
+}
+
+const char *Config::getSrcAppAt(int index) const
+{
+  return d_implementation->getSrcAppAt(index);
+}
+
+const char *Config::getDestAppAt(int index) const
+{
+  return d_implementation->getDestAppAt(index);
+}
+
+const char *Config::getSrcObjAt(int index) const
+{
+  return d_implementation->getSrcObjAt(index);
+}
+
+const char *Config::getDestObjAt(int index) const
+{
+  return d_implementation->getDestObjAt(index);
+}
+
+const char *Config::getWidthAt(int index) const
+{
+  return d_implementation->getWidthAt(index);
+}
+const char *Config::getCommTypeAt(int index) const
+{
+	return d_implementation->getCommTypeAt(index);
+}
+const char *Config::getProcMethodAt(int index) const
+{
+	return d_implementation->getProcMethodAt(index);
+}
+
+
+int Config::getNumDataMembers() const
+{
+	return d_implementation->getNumDataMembers();
+}
+
+const char *Config::getDataNameAt(int index) const
+{
+	return d_implementation->getDataNameAt(index);
+}
+
+bool Config::exists(const char *name) const
+{
+	return d_implementation->exists(name);
+}
+
+void Config::setBoolValue(const char *name, bool value)
+{
+		d_implementation->setStringValue(name, ConfigImpl::boolToString(value));
+	// d_implementation->setBoolValue(name, value);
+}
+
+bool Config::getBoolValue(const char *name) const
+{
+	return ConfigImpl::stringToBool(d_implementation->getStringValue(name));
+	//return d_implementation->getBoolValue(name);
+}
+
+void Config::setIntValue(const char *name, int value)
+{
+	d_implementation->setStringValue(name, ConfigImpl::intToString(value));
+	// d_implementation->setIntValue(name, value);
+}
+
+int Config::getIntValue(const char *name) const
+{
+	return ConfigImpl::stringToInt(d_implementation->getStringValue(name));
+	//return d_implementation->getIntValue(name);
+}
+
+void Config::setDoubleValue(const char *name, double value)
+{
+	d_implementation->setStringValue(name, ConfigImpl::doubleToString(value));
+	// d_implementation->setDoubleValue(name, value);
+}
+
+double Config::getDoubleValue(const char *name) const
+{
+	return ConfigImpl::stringToDouble(d_implementation->getStringValue(name));
+	//return d_implementation->getDoubleValue(name);
+}
+
+void Config::setStringValue(const char *name, const char *value)
+{
+	d_implementation->setStringValue(name, value);
+}
+
+const char * Config::getStringValue(const char *name) const
+{
+	return d_implementation->getStringValue(name);
+}
+
+void Config::setValue(const char *name, const char *value)
+{
+	d_implementation->setStringValue(name, value);
+}
+
+const char * Config::getValue(const char *name) const
+{
+	return d_implementation->getStringValue(name);
+}
+
+bool Config::deleteData(const char *name)
+{
+	return d_implementation->deleteData(name);
+}
+
+
+} // end namespace rude
diff --git a/rudeconfig/src/config.h b/rudeconfig/src/config.h
new file mode 100644
index 0000000..5989676
--- /dev/null
+++ b/rudeconfig/src/config.h
@@ -0,0 +1,637 @@
+// Config.h
+//
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
+// See file AUTHORS for contact information
+//
+// This file is part of RudeConfig.
+//
+// RudeConfig 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; either version 2, or (at your option)
+// any later version.
+// 
+// RudeConfig 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 should have received a copy of the GNU General Public License
+// along with RudeConfig; (see COPYING) if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//------------------------------------------------------------------------
+
+
+#ifndef INCLUDED_RUDE_CONFIG_H
+#define INCLUDED_RUDE_CONFIG_H
+
+#include <istream>
+
+namespace rude{
+
+namespace config{
+class ConfigImpl;
+}
+
+//=
+// rude::Config is the public interface for the config/ini file reader.
+//=
+class Config{
+
+	// Bridge component
+	//
+	rude::config::ConfigImpl *d_implementation;
+
+public:
+
+
+	//=
+	// Default constructor
+	// Use to obtain an instance of the rude::Config component
+	// 
+	// <b>Example:</b>
+	// <code>
+	// rude::Config myconfig;
+	// 
+	// //OR
+	// 
+	// rude::Config *myconfig = new rude::Config();
+	// </code>
+	//= 
+	Config();
+
+	//=
+	// Returns the version of the component.
+	// 
+	// The version is specified by <b>X.Y</B> where: 
+	// <B>X</B> is the version of the interface (this class), and
+	// <B>Y</B> is the version of the implementation (the internals).
+	// 
+	// <b>Example:</b>
+	// 
+	// <code>const char *version = Config::version();</code>
+	//=
+	static const char *version();
+
+	//=
+	// Sets the default filename to be used by all config objects
+	// Initially, this value is "default.ini"
+	// Methods affected include load(void) and save(void)
+	// This method does not affect already existing instances.
+	//=
+	static void setDefaultConfigFile(const char *filepath);
+
+	//=
+	// Returns the default filename to be used by all config objects
+	//=
+	static const char *getDefaultConfigFile();
+
+	//=
+	// Sets the default comment character to be used by all config objects
+	// The comment character affects how config files are parsed, and how they are written.
+	// Initially, the default comment character is set to '#' 
+	// This method does not affect already existing instances.
+	//=
+	static void setDefaultCommentCharacter(char c);
+
+	//=
+	// Returns the default comment character to be used by all config objects
+	//=
+	static char getDefaultCommentCharacter();
+
+
+	//=
+	// Sets the default delimiter character to be used by all config objects
+	// The delimiter affects how config files are parsed, and how they are written.
+	// Initially, the default delimiter is set to '=' 
+	// This method does not affect already existing instances.
+	//=
+	static void setDefaultDelimiter(char c);
+
+	//=
+	// Returns the default delimiter character to be used by all config objects
+	//=
+	static char getDefaultDelimiter();
+
+
+	//=
+	// Sets the default behavior of all config objects in dealing with deleted values.
+	// The default behavior is for config objects to preserve deleted data as comments when 
+	// the config object is saved
+	// This method does not affect already existing instances.
+	//=
+	static void setDefaultPreserveDeleted(bool shouldPreserve);
+
+	//=
+	// Returns the default deletion behavior
+	// true means deleted data will be preserved as comments when the config object is saved
+	// false means that deleted data will be discarded when the config object is saved
+	//=
+	static bool getDefaultPreserveDeleted();
+
+
+	//=
+	// Set's the default filepath to be used by the load() and save() methods
+	// The default filepath is initially set to "./default.ini"
+	// Affects the current instance only
+	//=
+	void setConfigFile(const char *filepath);
+
+	//=
+	// Returns the default filepath to be used by the load() and save() methods
+	// The default filepath is initially set to "./default.ini"
+	// Affects the current instance only
+	//=
+	const char * getConfigFile();
+
+	//=
+	// Sets whether or not deleted data will be preserved as comments.
+	// If set to true, deleted data will be converted into comments when 
+	// the save() method is called.  If set to false, deleted data
+	// will not be compeltely discarded. Default is false (no preserve).
+	// Affects the current instance only.
+	//=
+	void preserveDeletedData(bool shouldPreserve);
+
+	//=
+	// Set's the comment character ( initially set to '#' )
+	// If the comment character is set to NULL (0), 
+	// then comments will not be written when save() is called
+	// Affects the current object only
+	//=
+	void setCommentCharacter(char commentchar);
+
+	//=
+	// Set's the delimiter for new config objects ( initially set to '=' )
+	// If the delimiter is set to NULL, then it will be assumed that
+	// the key and value are separated by whitespace.
+	// Affects the current object only
+	//=
+	void setDelimiter(char kayvaluedelimiter);
+
+	//=
+	// 
+	// When called before load(), saves the configuration to the default config file.
+	// Initially, the default config file is "./default.ini".
+	// 
+	// If load was called with an argument:
+	//     load(const char *filename)
+	// then save() will use the same filename. 
+	// 
+	// The filename used by the instance can be changed by the setConfigFile() method.
+	//=
+	bool save();
+
+	//=
+	// Saves the configuration object to the specified file
+	// The default config file path for the instance is not altered...
+	// Use setConfigFile(const char *filename) or load(const char *filename) to set the default filename for the instance
+	//=
+	bool save(const char *filepath);
+
+	//=
+	// Removes the contents of the configuration file - completely wipes it out.
+	// Does not preserve anything.  Afterwards, the current section is set
+	// to the empty section (""), which is the unnamed section
+	// at the beginning of the configuration file.
+	//=
+	void clear();
+	
+	//=
+	// Loads the default file into the configuration object.
+	// By default, the current file is 'default.conf', 
+	// but can be overridden by calling the setConfigFile(const char *filename) method.
+	// This method does not clear the config object before loading.
+	// If you load two or more configuration files that have the same sections,
+	// they are effectively merged.  In this case, data members that have the same
+	// name will get the value of the last file loaded. This comes in handy if
+	// you load a global config file first, and you want to override
+	// some custom fields by subsequently loading a "preferences" file tailored to an individual.
+	// Use clear() if the config object already has data that you want to completely discard before loading
+	// a new file, or use another Config object instance.
+	//=
+	bool load();
+
+	//=
+	// Adds the file's configuration info to the current object.
+	// Does not delete any existing data in the config object. 
+	// The default config file path is not altered...
+	// Use setConfigFile() to permanently set the default config file for load() and save()
+	// This method does not clear the config object before loading.
+	// Use clear() if the config object already has data that you want to discard.
+	//=
+	bool load(const char *filename);
+
+	bool load(std::istream& file);
+
+	//=
+	// Returns the most recent error string, if there is one.
+	// If no error exists, it will return the empty string ("").
+	//=
+	const char *getError();
+
+        int getNumSourceDestMembers() const;
+        const char *getSrcObjAt(int index) const;
+        const char *getDestObjAt(int index) const;
+        const char *getSrcAppAt(int index) const;
+        const char *getDestAppAt(int index) const;
+        const char *getWidthAt(int index) const;
+        /* remedius
+         */
+        const char *getCommTypeAt(int index) const;
+        /* remedius
+         */
+        const char *getProcMethodAt(int index) const;
+
+	//=
+	// Returns the number of sections in the entire configuration file
+	// This number includes the default section - ""  (the empty section at the beginning of the file) 
+	// Sections within the configuration file are identifed by [Square Brackets] surrounding the name of the section.
+	// Whitespace surrounding the section name is ignored. So [   This Section    ] and [This Section] are identical.
+	// Section names <b>are</b> case sensitive.  
+	// The default section is the empty section - the unnamed section at the beginning of the file that
+	// exists before any other [named] sections. This section exists even if the first line of the file
+	// contains a [named section].  The empty section will simply be void of any data.
+	// As such, the return value will always be >= 1.
+	//=
+	int getNumSections() const;
+
+	//=
+	// Enumeration method to discover sections
+	// Returns the section name at the given index,
+	// or NULL if the index is out of range
+	// If the section has no name, but is a valid index, then it will return the empty string ("")
+	//=
+	const char *getSectionNameAt(int index) const;
+	
+	//=
+	// Sets the current working [section], possibly creating a new section
+	// The default section is "" (the untitled section at the beginning of the configuration file).  
+	// If the new section cannot be found, and <b>shouldCreate</b> is <b>true</b>,
+	//  then the section will be created and will exist at the end of all other sections.  
+	// If the new section cannot be found, and <b>shouldCreate</b> is <b>false</b>,
+	//  then the current section remains unchanged, and the method returns false.
+	// Leading and trailing whitespace is not preserved when the file is written,
+	//  and as such should be avoided when naming sections
+	//=
+	bool setSection(const char *sectionname, bool shouldCreate);
+
+	//=
+	// Sets the current working section, creating the section if it does not exist.
+	// See <b><i>setSection(const char *sectionname, bool shouldCreate)</i></b> where <i>shouldCreate</i> = true.
+	//=
+	bool setSection(const char *sectionname);
+
+	//=
+	// Deletes the section identified by <i>sectionname</i> and all data associated with it
+	// Returns false if the section does not exist or has already been deleted.
+	// If the object is saved, the entire section will be commented out.
+	// If, during the lifetime of this object, the section is re-created, then the section will be revived, but all
+	// previous data members remain commented (as if deleted) unless/until recreated (see deleteData())
+	//=
+	bool deleteSection(const char *sectionname);
+
+
+	//=
+	// Returns the number of data elements for the current section
+	//
+	// <b>Example:</b>
+	// 
+	// Given the following configuration:
+	// 
+	//<font color=red>[Good Movies]
+	// The 5th Element
+	// Resevoir Dogs
+	// Braveheart
+	// 
+	// [Bad Movies]
+	// 
+	// Freddy Got Fingered
+	// CONfidential
+	// 
+	// [Body Parts]
+	// arm=2
+	// head=1
+	// legs=2
+	// neck=1
+	// ears=2
+	// eyes=2
+	//	
+	// </font>
+	//
+	// You'll get the following results:
+	// <code> 
+	// config->setSection("Body Parts", true);
+	// config->getNumDataMembers(); // returns 6
+	//
+	// config->setSection("Bad Movies", true);
+	// config->getNumDataMembers(); // returns 2
+	//
+	// config->setSection("Good Movies", true);
+	// config->getNumDataMembers(); // returns 3
+	// </code>
+	//=
+	int getNumDataMembers() const;
+
+	//=
+	// Enumeration method to discover data members within the current section
+	// Returns the name of the data member at 
+	// the specified index within the current
+	// section, or NULL if the index is out of range.
+	//
+	// <b>Example:</b>
+	// 
+	// Given the following configuration:
+	// 
+	//<font color=red>[Contact Info]
+	// name= Mark Twain
+	// email address = mark@twain
+	// phone = 123.456.789
+	// </font>
+	//
+	// You'll get the following results:
+	// <code> 
+	// config->setSection("Contact Info");
+	// config->getDataNameAt(0); // returns "name"
+	// config->getDataNameAt(2); // returns "phone"
+	// config->getDataNameAt(3); // returns NULL (out of range)
+	//
+	// </code>
+	//=
+	const char *getDataNameAt(int index) const;
+
+	//=
+	// Returns true if a data member exists with the given 
+	//name within the current section
+	//
+	//
+	// &nbsp;<b>Example:</b>
+	// 
+	// Given the following configuration:
+	//
+	//<font color=red>
+	// [Strong Body Parts]
+	// arm=2
+	// head=1
+	// legs=2
+	// neck=1
+	//
+	// [Weak Body Parts]
+	//	eyes=2
+	// belly=1
+	// nose=1
+	// </font>
+	//
+	// You'll get the following results:
+	// <code> 
+	// config->setSection("Strong Body Parts");
+	// 
+	// if(config->exists("arm"))
+	// {
+	// 	// yes, arm exists...
+	// }
+	// 
+	// if(config->exists("belly"))
+	// {
+	// 	// returns false - belly isn't in that section.
+	// }
+	// 
+	// config->setSection("Weak Body Parts");
+	// 
+	// if(config->exists("belly"))
+	// {
+	//	// yes! belly is in this section....
+ 	// }
+	// </code>
+	//=
+	bool exists(const char *name) const;
+
+	//=
+	// Returns the boolean value of the data identified by <i>name</i> within the current section
+	// This is a helper function that converts the string data stored in the config object to a boolean
+	// Returns true if the current value is "on" or 1,
+	// or if the value starts with the letter 't' or 'y'
+	// ( all of the above are case insensitive )
+	// returns false otherwise
+	//
+	// As such, it will interpret the following as true:
+	// Yes, yes, On, on, True, true, 1, T, t, Y, y
+	//
+	// Likewise, it will interpret the following as false:
+	// No, no, Off, off, False, false, 0, F, f, N, n
+	//
+	// 
+	// <b>Example:</b>
+	// 
+	// Given the following configuration:
+	//
+	//<font color=red>
+	// [Things that are and aren't]
+	// Bed Bugs= TRUE
+	// Aliens = 1
+	// Freud= ON
+	// Water= yes
+	// ducks = false
+	// carpenter = off
+	// floppy = 0
+	// sand = Nope
+	// </font>
+	// You'll get the following results:
+	// <code> 
+	// config->setSection("Things that are and aren't");
+	// 
+	// config->getBoolValue("Aliens"); // returns true
+	// config->getBoolValue("carpenter"); // returns false
+	// // etc...
+	// </code>
+	//=
+	bool getBoolValue(const char *name) const;
+
+	//=
+	// Returns the integer value of the data identifed by <i>name</i> within the current section
+	// This is a helper function that converts the string value stored in the config object to an int.
+	// Returns 0 if the data does not exist or if an integer value cannot be determined.
+	//=
+	int getIntValue(const char *name) const;
+
+	//=
+	// Returns the double value, or 0 if a double value cannot be determined
+	// Thie is a helper function that converts the string value stored in the config object to a double
+	//=
+	double getDoubleValue(const char *name) const;
+
+	//=
+	// Returns the string-character value.
+	// Unless the value is quoted, leading and trailing whitespace is stripped.
+	// If the value is quoted, the quotes are removed, and leading and trailing whitespace
+	// within the quotes are preserved.
+	//=
+	const char * getValue(const char *name) const;
+
+	//=
+	// Same as <code>const char *getValue(const char *name)</code>
+	// @deprecated
+	//=
+	const char * getStringValue(const char *name) const;
+
+	//=
+	// Sets the named value within the current section to "true" or "false"
+	// This is a helper function that converts a bool to the string value
+	// that the config object expects.
+	// If the value is already set for the data item, the value is changed.
+	// If the value is not already set, it is created
+	// 
+	// <b>Example:</b>
+	// 
+	// To create the following configuration entries:
+	// 
+	// <font color=red>[On Sale]
+	//	Hard Drives = true
+	// Cases = false
+	// Keyboards = false
+	// </font>
+	//
+	// Use this code:
+	// <code> 
+	// config->setSection("On Sale");
+	// config->setBoolValue("Hard Drives", true);
+	// config->setBoolValue("Cases", false);
+	// config->setBoolValue("Keyboards", false);
+	// config->save();
+	// </code>
+	//
+	// @param name the identifying name of the data member
+	// @param value The integer value of the data member
+	//
+	//=
+	void setBoolValue(const char *name, bool value);
+
+	//=
+	// Sets the named value within the current section to the specified integer
+	// The config object stores values as strings- this is a helper method
+	// that converts an integer to the expected string value.
+	// If the value is already set for the data item, the value is changed.
+	// If the value is not already set, it is created
+	// 
+	// <b>Example:</b>
+	// 
+	// To create the following configuration entries:
+	// 
+	// <font color=red>[Inventory]
+	//	Hard Drives = 35
+	// Cases = 24
+	// Keyboards = 103
+	// </font> 
+	//
+	// Use this code:
+	// <code> 
+	// config->setSection("Inventory", true);
+	// config->setIntValue("Hard Drives", 35);
+	// config->setIntValue("Cases", 24);
+	// config->setIntValue("Keyboards", 103);
+	// config->save();
+	// </code>
+	//
+	// @param name the identifying name of the data member
+	// @param value The integer value of the data member
+	//
+	//=
+	void setIntValue(const char *name, int value);
+
+	//=
+	// Sets the value for a data item within the current section to the specified double
+	// The config object stores values as strings- this is a helper method
+	// that converts an integer to a string value to be stored.
+	// If the value is already set for the data item, the value is changed.
+	// If the value is not already set, it is created
+	// 
+	// <b>Example:</b>
+	// 
+	// To create the following configuration entries:
+	// 
+	// <font color=red>[Prices]
+	//	Hard Drives = 59.95
+	// Cases = 44.00
+	// Keyboards = 12.25
+	// </font> 
+	//
+	// Use this code:
+	// <code> 
+	// config->setSection("Prices", true);
+	// config->setDoubleValue("Hard Drives", 59.95);
+	// config->setDoubleValue("Cases", 44.00);
+	// config->setDoubleValue("Keyboards", 12.25);
+	// config->save();
+	// </code>
+	//
+	// @param name the identifying name of the data member
+	// @param value The double value of the data member
+	// @author Matt Flood
+	//
+	//=
+	void setDoubleValue(const char *name, double value);
+
+
+	//=
+	// Sets the value for a data item within the current section to the specified string
+	// If the value is already set for the data item, the value is changed.
+	// If the value is not already set, it is created.
+	// If leading and/or trailing whitespace exists within the value, it will be preserved in
+	// the config file.  The config object will automatically surround the value with quotes.
+	// Likewise, if the value starts with a quote ("), then the value
+	// will necessarily be surrounded by quotes to preserve it.  As such, programs do not have to, (and
+	// in fact should not ) perform their own quoting of values.  You should provide you own
+	// quotes only when you are modifying the config/ini file using a text editor or some other means
+	// besides the RudeConfig object.
+	//
+	// Note:  Leading and traling whitespace of the identifying fieldname (the key for the data item) is not preserved.
+	// 
+	// <b>Example:</b>
+	// 
+	// To create the following configuration entry:
+	// 
+	// <font color=red>[travel]<br>Travel Agent = Mary Johnson</font>
+	// 
+	// Use this code:
+	// <code> 
+	// config->setSection("travel", true);
+	// config->setStringValue("Travel Agent", "Mary Johnson");
+	// config->save();
+	// </code>
+	//
+	// @param name the identifying name of the data member
+	// @param value The string value of the data member
+	// @author Matt Flood
+	//
+	//=
+	void setValue(const char *name, const char *value);
+
+	//=
+	// Same as setValue(const char *name, const char *value);
+	// @deprecated
+	//
+	//=
+	void setStringValue(const char *name, const char *value);
+
+	//=
+	// Deletes the data member identified by <i>name</i> (if it exists) in the current section.
+	// If the configuration object is saved, 
+	// then the data member will be preserved by being commented out.
+	// If a new value is later assigned to this 
+	// value (in the lifetime of the instance),
+	// then it becomes undeleted (uncommented).
+	// Values can only be revived this way using the same instance they were deleted with.
+	// Otherwise, they become permanent comments.
+	// See <code>preserveDeletedData(bool shouldPreserve)</code> to alter this behavior.
+	//
+	//=
+	bool deleteData(const char *name);
+
+	~Config();
+
+};
+
+} // end namespace rude
+
+#endif
+
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..736099e
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,5 @@
+/Makefile
+/Makefile.in
+/TAGS
+/.deps
+/core
diff --git a/src/BIFO.cc b/src/BIFO.cc
new file mode 100644
index 0000000..de08fb4
--- /dev/null
+++ b/src/BIFO.cc
@@ -0,0 +1,196 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/BIFO.hh"
+
+#include "music/debug.hh"
+
+#if MUSIC_USE_MPI
+
+#include <cstring>
+#include "music/error.hh"
+
+namespace MUSIC {
+
+  void
+  BIFO::configure (int elementSize, int maxBlockSize)
+  {
+    elementSize_ = elementSize;
+    maxBlockSize_ = maxBlockSize;
+    size = maxBlockSize_;
+    buffer.resize (size);
+    beginning = 0;
+    end = 0;
+    current = 0;
+    top = 0;
+
+  }
+
+
+  // Duplicate the single element in the buffer to a total of nElements
+  // 0 is allowed as argument in which case the buffer is emptied
+  void
+  BIFO::fill (int nElements)
+  {
+    int neededSize = nElements * elementSize_;
+    if (neededSize > size)
+      grow (neededSize);
+
+    if (end - current != elementSize_)
+      error ("internal error: BIFO in erroneous state before fill");
+    
+    beginning = 0;
+    
+    if (nElements == 0)
+      {
+	end = 0;
+	current = 0;
+	top = 0;
+	return;
+      }
+
+    // Here we use the assumption that vector memory is contiguous
+    // Josuttis says this is the intention of STL even though the
+    // first version of the report is not clear about this.
+
+    if (current != 0)
+      {
+	memcpy (&buffer[0], &buffer[current], elementSize_);
+	current = 0;
+      }
+    
+    top = elementSize_;
+    end = nElements * elementSize_;
+    while (top < end)
+      {
+	memcpy (&buffer[top], &buffer[0], elementSize_);
+	top += elementSize_;
+      }
+  }
+
+  
+  bool
+  BIFO::isEmpty ()
+  {
+    return current == end;
+  }
+
+
+  void*
+  BIFO::insertBlock ()
+  {
+    beginning = end; // set insertion point to end of last block
+    if (current <= end) // reading below inserting?
+      {
+	// Inserting above current data
+
+
+	// Is it time to wrap around the insertion point?  This should
+	// only be done if we can fit a maximal block below current
+	// (current > maxBlockSize_).  We need to use > since a
+	// maximal block otherwise could cause an empty buffer.
+	if (current > maxBlockSize_)
+	  beginning = 0; // Wrap around!
+	else if (beginning + maxBlockSize_ > size) // Need to enlarge?
+	  // (The peculiar choice of growing just as much as we need
+	  // is made since buffers can be VERY large in large scale
+	  // simulations.)
+	  grow (beginning + maxBlockSize_);
+      }
+    else
+      {
+	// Inserting below current data
+	if (current - beginning <= maxBlockSize_) // Too tight?
+	  {
+	    // delta is how much more space we need + epsilon (8 to be
+	    // nice to memory)
+	    int delta = maxBlockSize_ - (current - beginning) + 8;
+	    if (size - top < delta) // Need to enlarge?
+	    // (The peculiar choice of growing just as much as we need
+	    // is made since buffers can be VERY large in large scale
+	    // simulations.)
+	      grow (size + delta);
+	    // Now move entire upper chunk of data:
+	    memmove (&buffer[current + delta], &buffer[current],
+		     top - current);
+	    current += delta;
+	    top += delta;
+	  }
+      }
+    return static_cast<void*> (&buffer[beginning]);
+  }
+
+
+  void
+  BIFO::trimBlock (int blockSize)
+  {
+    if (blockSize > 0)
+      {
+	end = beginning + blockSize;
+	if (end > size)
+	  {
+	    std::ostringstream msg;
+	    msg << "BIFO buffer overflow; received "
+		<< blockSize / elementSize_
+		<< ", room " << (size - beginning) / elementSize_
+		<< ", permitted " << maxBlockSize_ / elementSize_;
+	    error (msg);
+	  }
+	if (current <= end)
+	  top = end;
+      }
+  }
+
+
+  void*
+  BIFO::next ()
+  {
+    if (isEmpty ())
+      {
+	MUSIC_LOGR ("attempt to read from empty BIFO buffer");
+	return NULL;
+      }
+    
+    if (current == top)
+      {
+	// wrap around
+	current = 0;
+	top = end;
+      }
+    
+    // Here we use the assumption that vector memory is contiguous
+    // Josuttis says this is the intention of STL even though the
+    // first version of the report is not clear about this.
+    void* memory = static_cast<void*> (&buffer[current]);
+    /* remedius
+     * could it be possible that elementSize > size of received data? no
+     * changed from current+=elementSize_ to the following line:
+     */
+    current += std::min(elementSize_,top-current);
+    return memory;
+  }
+
+  void
+  BIFO::grow (int newSize)
+  {
+    size = newSize;
+    buffer.resize (size);
+  }
+    
+}
+#endif
diff --git a/src/ChangeLog b/src/ChangeLog
new file mode 100644
index 0000000..0f929e6
--- /dev/null
+++ b/src/ChangeLog
@@ -0,0 +1,1020 @@
+2013-07-09  Mikael Djurfeldt  <mdj@wand.pdc.kth.se>
+
+	* runtime.cc (Runtime::Runtime): Only create scheduling agents if
+	launched by MUSIC.
+
+2012-09-26  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am, connector.cc, event_router.cc, multibuffer.cc,
+	music/connectivity.hh, music/connector.hh, music/multibuffer.hh,
+	music/runtime.hh, music/scheduler.hh, music/subconnector.hh,
+	port.cc, runtime.cc, scheduler.cc, subconnector.cc: Implementation
+	of multiconnectors.
+
+2012-09-15  Mikael Djurfeldt  <djurfeldt@hambach.cluster>
+
+	* connector.cc (lessOutputSubconnector): Make less condition
+	consistent.
+
+2012-09-14  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* connector.cc (Connector::initialize): Sort input and output
+	subconnectors according to different criteria in order to obtain
+	the communication schedule described in Mikael Djurfeldt et
+	al. (2005) "Massively parallel simulation of brain-scale neuronal
+	network models."
+
+	* music/connector.hh (Connector::isInput)
+	(InputConnector::isInput): New member function.
+
+	* music/subconnector.hh (Subconnector::localRank): New member
+	function.
+
+2012-09-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/clock.hh, clock.cc (Clock::reset): New member function.
+
+2012-09-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* scheduler.cc (Scheduler::nextCommunication): Make sure that all
+	events from the first point in time are scheduled.
+
+	* music/scheduler.hh (SConnection): Renamed from Connection in
+	order not to be confused with connection.hh::Connection.
+
+	* connector.cc (Connector::isProxy): New member function.
+
+	* music/scheduler.hh, scheduler.cc (Scheduler::addConnection): New
+	argument multiComm.
+	(Scheduler::Connection): New member multiComm.
+
+	* music/temporal.hh, temporal.cc (ConnectionDescriptor): New
+	member multiComm.
+	(TemporalNegotiator::collectNegotiationData): Set multiComm.
+	(TemporalNegotiator::fillScheduler): Pass multiComm to
+	Scheduler::addConnection.
+
+2012-09-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* scheduler.cc (Scheduler::initialize): Setup ProxyConnector
+	representing a distant connection.
+
+	* music/scheduler.hh (Scheduler::Node): New member functions
+	leader and nProcs.
+
+	* music/scheduler.hh, scheduler.cc (Scheduler::addNode,
+	Scheduler::Node::Node): New arguments leader and nProcs.
+
+	* music/setup.hh, setup.cc (Setup::nProcs): New member function.
+
+	* music/temporal.hh (TemporalNegotiationData): Added new members
+	leader and nProcs.
+
+	* temporal.cc (TemporalNegotiator::collectNegotiationData): Set
+	leader and nProcs.
+	(TemporalNegotiator::fillScheduler): Pass leader and nProcs to
+	Scheduler::addNode.
+
+	* music/connector.hh (ProxyConnector): New class. These objects
+	will represent connections which the local application doesn't
+	participate in but still need to be aware of in order to schedule
+	common collective communication events.
+
+2012-09-02  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/event_router.hh, event_router.cc (DirectRouter): New
+	class.
+
+	* music/setup.hh, setup.cc (Setup::leader): Added selector.
+
+	* music/configuration.hh, configuration.cc
+	(Configuration::leader): Added selector.
+
+2012-08-27  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/spatial.hh, spatial.cc: Simplification made possible by
+	previous change.
+
+	* spatial.cc (SpatialNegotiator::send)
+	(SpatialNegotiator::receive): First send size of receive buffer in
+	order to avoid successive resizing. This is kinder to the memory
+	allocator.
+
+2012-08-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/memory.hh, memory.cc: New files.
+
+	* Makefile.am, runtime.cc: Report memory usage for world rank #0
+	using mallinfo.
+
+	* music/runtime.hh, runtime.cc, music/connector.hh: Initial
+	support for MultiConnector:s. MultiConnector is an object
+	governing simultaneous communication through a set of
+	Connector:s.
+
+	* runtime.cc, music/connector.hh, music/subconnector.hh: Added
+	some debugging/analysis code.
+
+2012-08-23  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/scheduler.hh (Scheduler::Node::outputConnections),
+	scheduler.cc: Pass outputConnections as a pointer rather than as a
+	vector.
+
+	* event_routing_map.cc (OutputRoutingMap::fillRouter): Bugfix:
+	return -> continue.
+
+	* interval.cc: New file.
+
+	* music/interval.hh: Make Interval:s printable.
+
+	* music/music-config.hh-in: (and many other files) Some #include
+	reorganization: Let those who need it include music-config.hh as
+	the common first header file.
+
+	* music/ordered_ilist.hh (OrderedIList::iterator): Satisfy BG/P
+	compiler which complained that an OrderedIList member creates a
+	circular reference with respect to type.
+
+2012-08-22  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/port.hh, port.cc (Port::checkIndexMap): New member.
+
+	* port.cc (OutputPort::mapImpl, InputPort::mapImpl: Use
+	checkIndexMap.
+
+	* event_routing_map.cc (OutputRoutingMap::fillRouter): Ask
+	EventRouter if it needs as few points as possible rather than as
+	few intervals as possible, and close gaps only in the latter case.
+	This is important when using the new table based routing together
+	with simulators with round-robin allocation, such as NEST.
+
+	* music/event_router.hh: Let table based routers say that they
+	need few points rather than intervals.
+
+2012-08-21  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/interval_table.hh, music/ordered_ilist.hh: Introduced an
+	interval table optimization variable MUSIC_ITABLE_FLAVOR with the
+	options MUSIC_VANILLA, MUSIC_TRIMMED, MUSIC_COMPACT and
+	MUSIC_SCATTERED explained at the top of music/interval_table.hh.
+
+	* music/event_router.hh: #define MUSIC_ITABLE_FLAVOR to
+	MUSIC_SCATTERED.
+
+	* music/interval_table.hh (IntervalTable::search): Check index
+	against tableSize_ instead of container size.
+
+	* music/subconnector.hh, music/event_routing_map.hh: Don't
+	#include <music/event_router.hh> which contains heavy template
+	stuff. Instead forward declare EventRouter.  Since both
+	subconnector.hh and event_routing_map.hh are included by other
+	header files, this speeds up compilation and decreases the
+	dependencies in the code tree.
+
+	* connector.cc, event_routing_map.cc, port.cc, subconnector.cc:
+	#include "music/event_router.hh".
+
+	* runtime.cc (Runtime::tick): Only access first element of
+	schedule if non-empty.
+	(Runtime::finalize): Only do schedule-related processing if
+	schedule initially non-empty.
+
+	* Makefile.am: Added music/interval_table.hh,
+	music/ordered_ilist.hh.
+
+	* music/interval_table.hh, music/ordered_ilist.hh: New files.
+
+	* music/event_router.hh: Use new IntervalTable template.
+
+2012-08-19  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/event_routing_map.hh, event_routing_map.cc
+	(EventRoutingMap::build): Removed. Replaced by fillRouter which is
+	now public.
+
+	music/port.hh (EventOutputPort::setupCleanup), port.cc
+	(EventOutputPort::buildTable), connector.cc
+	(EventInputCollectiveConnector::spatialNegotiation): Use
+	EventRoutingMap::fillRouter and call EventRouter::buildTable
+	directly. Delete the event routing map before calling buildTable
+	so that the data structures used by buildTable don't co-exist in
+	memory with the event routing map.
+
+2012-08-18  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/interval_tree.hh, music/collector.hh, collector.cc,
+	music/distributor.hh, distributor.cc, event_routing_map.cc:
+	Separated the template DataType parameter of IntervalTree into
+	IntervalType and DataType.
+
+	* Makefile.am, music/event_routing_map.hh, event_routing_map.cc,
+	music/connector.hh, music/port.hh: Renamed
+	event_routingmap.{cc,hh} -> event_routing_map.{cc,hh}.
+
+	* music/interval_tree.hh: Optimized memory usage.
+
+2012-08-17  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/index_map.hh, music/interval.hh: Removed clone().
+
+	* connector.cc, music/event_router.hh, event_router.cc,
+	event_routingmap.cc, music/event.hh: Removal of indirection and
+	virtual pointers for IndexProcessors.
+
+	* music/event_router, event_router.cc: Removed unused member Data ().
+
+	* interval.hh, music/event_router.hh, event_router.cc,
+	event_routingmap.cc: Simplifications enabled by previous changes.
+
+	* music/event_router.hh, event_router.cc: Removed indirection
+	(pointer) to EventRoutingData from the IntervalTree through the
+	use of templates.
+
+	* port.cc: Let type dispatch happen here instead of in the
+	interval tree.
+
+	* event_routingmap.cc: Formatting.
+
+	* music/collector.hh, collector.cc, music/distributor.hh,
+	distributor.cc: Reverted to old use of interval_tree.
+
+	* music/interval_tree.hh: Reverted to version in trunk, but with
+	an added assignment operator.
+
+2012-08-17  Mikael Djurfeldt  <mdj@djurfeldt.com>
+
+	* application_map.cc (ApplicationMap::read): Only create file
+	"leaders" if MUSIC_DEBUGGING is defined.
+
+	* configuration.cc (Configuration::getEnv): Handle the case where
+	the MUSIC configuration variable is not present (launched without
+	MUSIC) properly.
+
+2012-08-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* scheduler.cc (Scheduler::Node::advance): Define time variable
+	only if debugging. Formatting changes.
+
+	* music/data_map.hh (~DataMap::DataMap), music/event_router.hh
+	(~IndexProcessor::IndexProcessor), music/index_map.hh
+	(~IndexMap::IndexMap)
+	(~IndexMap::IteratorImplementation::IteratorImplementation),
+	music/interval.hh (~Interval::Interval), music/spatial.hh
+	(~NegotiationIterator::Implementation::Implementation: Destructor
+	made virtual.
+
+	* music/collector.hh (Collector::Interval::clone),
+	music/distributor.hh (Distributor::Interval::clone): Added for
+	consistency.
+
+	* event_router.cc, music/event_router.hh, music/collector.hh,
+	music/distributor.hh, music/interval.hh, music/index_map.hh,
+	music/interval_tree.hh: Renamed Clone --> clone throughout.
+
+	* event_router.cc, music/event_router.hh: Renamed "spicialized"
+	--> "specialized" throughout.
+
+	* application_map.cc (ApplicationMap::assignLeaders): Only create
+	ranks file if MUSIC_DEBUG is defined.
+
+2012-08-07  Mikael Djurfeldt  <mdj@ubuntu-11.10>
+
+	* runtime.cc (runtime.cc): Disable deletion of ports.
+
+2012-08-03  Mikael Djurfeldt  <mdj@ubuntu-11.10>
+
+	* music/version.hh.in: New file.
+
+2012-03-20  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* setup.cc, music/setup.hh (Setup::maybeProcessMusicArgv): New
+	method.  Get argc and argv from MUSIC_ARGV, if available.
+
+2012-03-18  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* runtime.cc (Runtime::Runtime): Call maybepostponedSetup ().
+
+	* configuration.cc (MUSIC): Added comment with syntax of
+	_MUSIC_CONFIG_.
+
+2012-03-15  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/setup.hh, setup.cc (maybePostponedSetup, fullInit): New
+	functions.
+
+	* music/configuration.hh, configuration.cc
+	(Configuration::postponeSetup): New function.
+
+	* port.cc (Port::Port): Call maybepostponedSetup ().
+
+2011-11-24  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am (libmusic_la_LDFLAGS): Added libmpidep.la in order
+	to support predictRank.
+
+	* music/predict_rank.hh, predict_rank.cc: New files.
+
+2011-01-31  Mikael Djurfeldt  <mdj@djurfeldt.com>
+
+	* Makefile.am (libmusic_c_la_DEPENDENCIES): Added in order to
+	support parallel builds.
+
+2011-01-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* subconnector.cc (ContInputSubconnector::receive): Update receive
+	buffer pointer for subsequent receives when large packages have
+	been split.
+
+	* BIFO.cc (BIFO::insertBlock): Fixes to logic when buffer has
+	wrapped around.
+
+2010-07-28  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.7
+
+	* synchronizer.cc (Synchronizer::nextCommunication): Revert
+	buggy handling of tight loops in change of 2009-10-23.
+
+	* subconnector.cc
+	(MessageOutputSubconnector::MessageOutputSubconnector): Bugfix:
+	Initialize synchronizer pointer properly.
+
+2009-10-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.6
+
+	* ioutils.c, parse.cc: Added #include <cstdio>.
+
+2009-10-24  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.5
+
+2009-10-23  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* synchronizer.cc (Synchronizer::nextCommunication): Handle
+	tight loops (maxBuffered == 0) of spike events.
+
+	* temporal.cc (TemporalNegotiator::combineParameters): Correctly
+	take MAX_BUFFERED_NO_VALUE arguments into consideration.
+
+	* music/subconnector.hh, connector.cc, runtime.cc,
+	subconnector.cc: Use COMM_WORLD ranks for the pair-wise
+	communication schedule in Runtime::buildSchedule.
+
+	* music/port.hh, port.cc (EventOutputPort::EventOutputPort,
+	EventInputPort::EventInputPort): Moved from header file to
+	port.cc.
+
+	* temporal.cc (TemporalNegotiator::distributeNegotiationData): Use
+	type ClockState for accLatency.
+
+2009-10-20  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* connector.hh, event_router.hh, interval.hh, port.hh,
+	connector.cc, event_router.cc, port.cc: New version of event
+	routing interval joining code which handles interval sequences for
+	different targets separately.
+
+2009-10-19  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* event_router.cc (EventRouter::buildTable): Added debugging
+	printout of routing table size (when #define MUSIC_DEBUG is
+	uncommented).
+
+	* music/interval_tree.hh (IntervalTree<PointType)
+	(DataType>::size): New method (for debugging purposes).
+
+2009-10-12  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* setup.cc (Setup::Setup): Report an error if MPI::Init has been
+	called.
+
+2009-10-05  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/connector.hh, music/event_router.hh, music/port.hh,
+	connector.cc, event_router.cc, port.cc: Join event routing
+	intervals over holes in the routing map.  This increases
+	efficiency of event routing but has the consequence that
+	non-mapped indices may now be erroneously routed.
+
+2009-10-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music-c.h: (MUSIC_EventOutputPort_mapGlobalIndex)
+	(MUSIC_EventOutputPort_mapLocalIndex): Inserted missing
+	declarations.  (Thanks to Michael Hines.)
+
+	* Makefile.am (musicinclude_HEADERS): Removed duplicate
+	message.hh.
+
+2009-04-01  Mikael Djurfeldt  <djurfeldt@nada.kth.se>
+
+	* Release 1.0.4
+
+2009-03-15  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/spatial.hh, spatial.cc (NegotiationIterator): Join
+	intervals.  (In some cases this allows thousands of routing
+	intervals to be replaced by a single one.)
+
+	* runtime.cc (Runtime::finalize): Only include Barrier call for
+	OpenMPI versions <= 1.2.
+
+	* music/temporal.hh,
+	temporal.cc (TemporalNegotiator::computeDefaultMaxBuffered):
+	Select a proper default buffering for message ports.
+
+	* spatial.cc (SpatialInputNegotiator::negotiateWidth): Set
+	maxLocalWidth_ when given wildcard index.
+
+2009-03-14  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/connector.hh, music/subconnector.hh, connector.cc,
+	subconnector.cc: Moved buffer from subconnector to connector for
+	MessageOutputPorts.
+
+	* music/subconnector.hh (BufferingOutputSubconnector): New class.
+
+	* music/FIBO.hh, FIBO.cc (FIBO::clear, FIBO::nextBlockNoClear):
+	New member functions.
+
+	* port.cc (MessageInputPort::mapImpl): Give correct routing
+	information in the indexMap.
+
+	* music/port.hh, port.cc (MessageInputPort::map): Cover all
+	argument combinations.
+
+	* music/index_map.hh, index_map.cc (Index::WILDCARD_MAX): New
+	member.
+
+	* spatial.cc: Accept wild card indices on receiver side.
+
+	* subconnector.cc (EventInputSubconnectorGlobal::receive,
+	EventInputSubconnectorLocal::receive,
+	MessageInputSubconnector::receive): Define `data' as vector of
+	char, not vector of char*.
+
+2009-03-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.3
+
+	* setup.cc: #include "config.h"
+
+2009-03-12  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/temporal.hh, temporal.cc
+	(class TemporalNegotiator,
+	TemporalNegotiator::createNegotiationCommunicator,
+	TemporalNegotiator::~TemporalNegotiator): Keep handles to MPI
+	groups throughout communication.
+
+	* runtime.cc (Runtime::finalize): Call Connector::freeIntercomm
+	(); Include a barrier call to make freeing work under OpenMPI.
+
+	* music/connector.hh, connector.cc (Connector::freeIntercomm): New
+	member function.
+
+2009-03-12  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.2
+
+	* version.cc: Updated to version 1.0.2.
+
+2009-03-11  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* setup.cc: Conditionally delete temporalNegotiator.
+
+	* music/port.hh
+	(OutputRedistributionPort::OutputRedistributionPort,
+	InputRedistributionPort::InputRedistributionPort): New
+	constructors: Initialize spatialNegotiator to NULL pointer.
+
+	* port.cc (OutputRedistributionPort::setupCleanup,
+	InputRedistributionPort::setupCleanup): Conditionally delete
+	spatialNegotiator.  (It has not been allocated if the port has not
+	been mapped.)
+
+	* music/BIFO.hh, music/clock.hh, music/connector.hh,
+	music/subconnector.hh, music/synchronizer.hh, music/temporal.hh,
+	BIFO.cc, clock.cc, connector.cc, port.cc, runtime.cc,
+	subconnector.cc, synchronizer.cc, temporal.cc: Major revision of
+	timing logic.  Cont ports can now be connected in loops.
+
+2009-03-09  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* synchronizer.cc (Synchronizer::setMaxDelay (ClockState)): Moved
+	decrementing of localTime to Runtime::initialize.
+	(Synchronizer::setMaxDelay (ClockState, Clock&)): Use
+	Clock::setClockTicks to set startTime. (setMaxDelay may be called
+	multiple times.)
+
+	* runtime.cc (Runtime::initialize): Decrement localTime one tick
+	here.
+
+	* music/temporal.hh, temporal.cc
+	(TemporalNegotiator::distributeParameters): New function.
+
+	* collector.cc: Collector shouldn't make assumptions and compute a
+	"better" maxBlockSize-value for the buffers.  Instead use
+	allowedBuffered as given when configured.
+
+	* connector.cc: Configure compute the actual needed buffer size
+	here instead.
+
+	* music/clock.hh, clock.cc (Clock::setClockTicks): New function.
+
+	* BIFO.cc (BFIO::trimBlock): More informative overflow message.
+
+2009-03-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* synchronizer.cc, port.cc, music/temporal.hh: Decrement
+	maxBuffered at the proper place.  (This fixes a bug where the loop
+	algorithm worked on different parameters than the timing schedule
+	algorithm.)
+
+	* music/debug.hh (MUSIC_LOGBR): New debug macro.
+
+	* synchronizer.cc: Inserted some debugging statements.
+
+	* port.cc (OutputRedistributionPort::setupCleanup,
+	InputRedistributionPort::setupCleanup):  Delete spatialNegotiator
+	at end of setup phase.
+
+	* music/connector.hh, connector.cc, runtime.cc: Resolve a memory
+	allocation problem so that we leak less memory.
+
+	* port.cc (ContInputPort::mapImpl): Don't call assertInput ()
+	here.
+
+	* music/error.hh, music/port.hh, music/runtime.hh, music/setup.hh,
+	error.cc, port.cc, runtime.cc, setup.cc (Setup::Setup,
+	Runtime::Runtime, Port::map): Added error messages when trying to
+	call repeatedly.
+
+2009-03-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.1
+
+	* music/connector.hh, music/port.hh, music/spatial.hh,
+	music/subconnector.hh, music/temporal.hh, configuration.cc,
+	connector.cc, port.cc, spatial.cc, subconnector.cc, temporal.cc:
+	Pass MPI::Datatype to ContSubconnectors; Some code cleanups.
+
+2009-03-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/synchronizer.hh, synchronizer.cc, connector.cc: Removed
+	some old cruft in timing logic.
+
+	* sampler.cc: #include <cstring>
+
+	* setup.cc (Setup::publishMessageInput,
+	Setup::publishMessageOutput): Added.
+
+	* Makefile.am: Link shared library against MPI.
+
+	* music/port.hh, port.cc: Bugfixed error reporting.
+
+	* Makefile.am: Don't accept unresolved symbols in the shared library.
+
+	* music/version.hh, version.cc: New files.
+
+	* Makefile.am: Added ditto.
+
+	* Makefile.am: Set shared library version 1.0.0. (Note that this
+	version number follows different rules than the MUSIC version.)
+
+	* port.cc (Port::assertOutput, Port::assertInput, Port::hasWidth,
+	Port::width): Supply port name in error messages.
+
+	* connectivity.cc (Connectivity::add): Pass port name to
+	ConnectivityInfo constructor.
+
+	* music/connectivity.hh (ConnectivityInfo): Added portName (to be
+	used for more comprehensible error messages).
+
+2009-03-05  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* setup.hh (class Setup): Hide internal API as private.
+
+	* music/connector.hh, music/runtime.hh, music/setup.hh,
+	music/spatial.hh, music/subconnector.hh, music/temporal.hh,
+	connector.cc, port.cc, runtime.cc, setup.cc, spatial.cc,
+	subconnector.cc, synchronizer.cc, temporal.cc: Begin to reorganize
+	connectors so that functionality for setup and not needed during
+	runtime is moved to the new class Connection.
+
+	* music/connection.hh, connection.cc: New files.
+
+	* Makefile.am: Updated.
+
+	* music/temporal.hh, temporal.cc (ConnectionEdge): Renamed from
+	"Connection".
+
+2009-03-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0
+
+2009-02-27  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* ChangeLog, Makefile.am, music/FIBO.hh, music/array_data.hh,
+	music/clock.hh, music/connector.hh, music/data_map.hh,
+	music/event.hh, music/interval.hh, music/port.hh,
+	music/runtime.hh, music/spatial.hh, music/subconnector.hh,
+	music/synchronizer.hh, music/temporal.hh, FIBO.cc, array_data.cc,
+	clock.cc, connector.cc, port.cc, runtime.cc, spatial.cc,
+	subconnector.cc, synchronizer.cc, temporal.cc: Continous data port
+	framework.
+
+	* music/BIFO.hh, music/collector.hh, music/distributor.hh,
+	music/sampler.hh, BIFO.cc, collector.cc, distributor.cc,
+	sampler.cc: New files.
+
+2009-02-16  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am (libmusic_la_SOURCES): Added distributor.cc,
+	music/distributor.cc, collector.cc, music/collector.hh.
+
+	* music/spatial.hh, spatial.cc: Added destructor which destroys
+	indices.
+
+	* setup.cc, runtime.cc: Pass connectors even if not launched using
+	the music utility.
+
+2009-02-11  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music-c.h, music-c-c.c, music-c.cc (MUSIC_setupCommunicator):
+	Declare properly and don't use MPI_Intracomm.
+
+2009-02-09  Mikael Djurfeldt  <mdj@lampetra.csc.kth.se>
+
+	* music/subconnector.hh,
+	subconnector.cc (InputSubconnector::flushed): Bugfix: Initialize.
+
+	* error.cc, music/error.hh (error0): Report errors only from MPI
+	process rank 0.
+
+	* music/temporal.hh, temporal.cc: Implemented distribution of
+	allowed buffering using a loop detection algorithm.
+
+2009-02-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* FIBO.cc, connector.cc, music/FIBO.hh, music/connector.hh,
+	music/event.hh, music/runtime.hh, music/subconnector.hh,
+	music/synchronizer.hh, runtime.cc, subconnector.cc,
+	synchronizer.cc: Flush buffers at MUSIC::finalize.
+
+2009-02-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/connector.hh, music/spatial.hh, music/synchronizer.hh,
+	music/temporal.hh, port.cc, spatial.cc, synchronizer.cc,
+	temporal.cc: Compute default maxBuffered value based on
+	temporal.hh:DEFAULT_PACKET_SIZE.
+
+2009-02-05  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/setup.hh, music/synchronizer.hh, music/temporal.hh,
+	runtime.cc, setup.cc, temporal.cc: Bugfix: Convert accLatency to
+	ClockStateT.
+
+	* clock.cc, connectivity.cc, connector.cc, music/clock.hh,
+	music/connectivity.hh, music/connector.hh, music/debug.hh,
+	music/runtime.hh, music/setup.hh, music/synchronizer.hh,
+	music/temporal.hh, runtime.cc, setup.cc, spatial.cc,
+	synchronizer.cc, temporal.cc: Timing for applications with
+	different inter-tick-intervals may now work.
+
+2009-01-27  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* clock.cc, connector.cc, music/clock.hh, music/connector.hh,
+	music/runtime.hh, music/setup.hh, music/synchronizer.hh,
+	music/temporal.hh, port.cc, runtime.cc, setup.cc, subconnector.cc,
+	synchronizer.cc, temporal.cc: First steps of the timing algorithm.
+
+2008-12-02  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Switch to CamelCase.
+
+2008-11-05  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/interval_tree.hh: Bugfix: Compute the size of the binary
+	tree correctly.
+
+2008-11-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/connectivity.hh, connectivity.cc: Modified
+	connectivity_map to use indices rather than pointers (which cause
+	problems when the vector of connections is resized).
+
+	* music/debug.hh: New file.
+
+2008-11-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* FIBO.cc (FIBO::FIBO, FIBO::grow): Bugfix: Use resize instead of
+	reserve on buffer vector, otherwise old elements are not
+	guaranteed to be copied.
+
+	* music/event.hh (event::event): New constructor.
+	(event::operator<): New operator.
+
+	* port.cc (port::has_width, port::width): Added some error
+	checking.
+
+	* music/spatial.hh,
+	spatial.cc (spatial_negotiator::wrap_intervals): Compute local
+	offset differently depending on index::type argument.
+
+	* music/index_map.hh (index_interval::set_local): New member
+	function.
+
+	* linear_index.cc, permutation_index.cc: Correctly compute local
+	index offset.
+
+	* configuration (configuration::configuration,
+	configuration::~configuration): Create and delete application_map
+	and connectivity also when not launched under music.
+
+	* event_router.cc (event_router::insert_event): Always subtract
+	local offset (not subtracting requires that all offsets are zero
+	which only happens either if both sides use global indices or if
+	both sides use local indices which even out).
+
+2008-10-31  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/spatial.hh, spatial.cc (negotiate_width): Error check
+	width.
+
+	* music/event_router.hh (inserter_global): Offsets are negative
+	due to the spatial negotiation algorithm.
+
+	* music/spatial.hh, spatial.cc (intersect_to_buffers): New
+	implementation which allows index_maps for different MPI processes
+	to overlap.  The new algorithm is O (NP^2) where N is the number of
+	indices and P the number of processes.  (The old one was O (N).)
+
+	* music/permutation_index.hh, permutation_index.cc: Implemented.
+
+	* music/index_map.hh (index_map): Use value semantics (so that we
+	can copy the position by copying the iterator).
+
+	* music/linear_index.hh (linear_index): Ditto.
+
+2008-10-30  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* spatial.cc: Bugfix: Changed MPI::INTEGER (Fortran) -> MPI::INT
+
+	* spatial.hh (TRANSMITTED_INTERVALS_MAX): New constant.
+
+	* spatial.cc (spatial_negotiator::send,
+	spatial_negotiator::receive): Allow transmission of an arbitrary
+	number of spatial negotiation intervals.
+
+	* subconnector.hh (SPIKE_BUFFER_MAX): New constant.
+
+	* subconnector.cc (event_output_subconnector::send,
+	event_input_subconnector_global, event_input_subconnector_local):
+	Allow transmission of an arbitrary number of spikes.
+
+	* spatial.cc (spatial_output_negotiator::negotiate): Bugfix: Use
+	remote_n_proc instead of n_processes when sending to remote side.
+
+	* music/application_map.hh, application_map.cc, index_map.cc,
+	music/interval.hh, music/interval_tree.hh, music/ioutils.hh,
+	ioutils.cc, music/spatial.hh, spatial.cc, music/subconnector.hh,
+	subconnector.cc, music/temporal.hh, temporal.cc: New files.
+
+	* Changes throughout to implement propagation of configuration
+	information and routing of spikes.
+
+2008-10-16  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/FIBO.hh (FIBO::buffer): Bugfix: Changed to vector of char
+	instead of char*.
+
+2008-10-14  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/port.hh, port.cc (port::is_connected): Make sure this
+	method works also in the runtime phase.
+
+2008-10-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am, music/FIBO.hh, FIBO.cc, clock.cc,
+	music/configuration.hh, configuration.cc, music/connector.hh,
+	connector.cc, music/event_router.hh, event_router.cc,
+	music/port.hh, port.cc, music/runtime.hh, runtime.cc,
+	music/setup.hh, setup.cc, synchronizer.cc: A first, cheating,
+	approximation of the implementation of spike communication.  Will
+	be followed by cleanups and real implementation.  The present
+	implementation only allows two applications with an output and
+	input port respectively.  The ports have a constant width given in
+	ports.hh and the sender and receiver application must have equal
+	number of MPI processes.
+
+	* music/connectivity.hh, connectivity.cc: New files.
+
+2008-10-10  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/index_map.hh (local_index::local_index,
+	local_index::local_index): New constructor.
+
+	* music-c.h, music-c.cc (MUSIC_event_input_port_map_global_index,
+	MUSIC_event_input_port_map_local_index): Replacing
+	MUSIC_event_input_port_map.
+
+	* music/port.hh (event_input_port): Added facilities to support C
+	interface.
+
+	* music/port.hh, port.cc (event_input_port::map): Take
+	event_handler_global_index and event_handler_local_index instead
+	of event_handler in second argument.
+
+	* music/event.hh (event_handler_global_index,
+	event_handler_local_index): New classes which replace
+	event_handler.
+
+	* music/port.hh, port.cc (insert_event): Replaced old method with
+	two new, one with a second argument local_index, and an overloaded
+	version with global_index.
+
+	* music/index_map.hh (global_index, local_index): New classes.
+
+2008-10-09  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/event_data.hh, music/message_data.hh: Removed.
+
+	* music/event.hh (event_handler::operator ()): Made virtual and
+	corrected arguments to adhere to RFC.
+
+	* port.cc (event_output_port::insert_event): Send spikes to event
+	router.
+
+	* Makefile.am (libmusic_la_SOURCES): Added event_router.cc,
+	music/event_router.hh
+
+	* music/event_router, event_router.cc: New files.
+
+2008-10-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* runtime.cc (runtime::runtime): Initialize my_communicator and
+	schedule.
+
+	* music/connector.hh, connector.cc: Connectors take over the role
+	of subconnectors.
+
+2008-10-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/port.hh, port.cc (event_output_port::insert_event): New method.
+
+2008-09-23  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* setup.cc (setup::setup): Compile use of MPI::Init_thread
+	conditionally.
+
+	* music-c.cc: #include <ctsring>.
+
+2007-11-26  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am (libmusic_la_SOURCES): Added music/spike_data.hh,
+	spike_data.cc.
+
+	* spike_data.cc: New file.
+
+2007-11-23  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/spike_data.hh: New file.
+
+	* music/setup.hh (setup::publish): Removed
+	(setup::publish_input, setup::publish_output): New methods.
+
+	* music/array_data.hh, music/data_map.hh, music/index_map.hh,
+	music/linear_index.hh: Added copyright notice + #ifdef logic.
+
+	* music/array_data.hh (array_data::array_data): Data type argument
+	moved first; added new constructor for linear arrays.
+
+	* Makefile.am: Added music/port.hh, port.cc.
+
+	* music/port.hh, port.cc: New files.
+
+	* music/runtime.hh (runtime::input_ports, runtime::output_ports):
+	New members.
+
+2007-11-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* configuration.cc (configuration::configuration): Handle dirct
+	launch by mpirun.
+
+	* music/configuration.hh (setup::launched_by_music): New method.
+
+	* music/configuration.hh (setup::_launched_by_music): New private
+	member.
+
+	* music/setup.hh, setup.cc (setup::my_communicator): Renamed from
+	myCommunicator.
+
+	* parse.cc (parser::parse_string, parser::next_arg): Use int
+	instead of char to handle characters.
+
+	* configuration.cc (configuration::configuration,
+	configuration::tap): Use int instead of char to handle
+	characters.
+
+2007-11-02  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/setup.hh, music/parse.hh: Don't #include
+	<music/application_map.hh>.
+
+	* music/setup.hh: #include <music/configuration.hh>.
+
+2007-11-01  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/error.hh, error.cc: Added.
+
+	* music/parse.hh, parse.cc: Moved here from utils subdirectory.
+
+	* music/configuration.hh, condiguration.cc
+	(configuration::configuration, configuration::lookup,
+	configuration::write_env,
+	configuration::insert, configuration::color): New methods.
+
+	* music/application_map.hh, application_map.cc: Moved to utils
+	subdirectory.
+
+	* Makefile.am (libmusic_la_SOURCES): Removed
+	music/application_map.hh, application_map.cc; Added
+	music/parse.hh, parse.cc.
+
+	* music/setup.hh, setup.cc: Rewritten.
+
+2007-10-26  Örjan Ekeberg  <orjan@nada.kth.se>
+
+	* runtime.cc, music/runtime.hh: Use type Intracomm for communicator.
+
+2007-10-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am: Added configuration.cc, music/configuration.hh,
+	application_map.cc music/application_map.hh.
+
+	* application_map.cc, music/application_map.hh: New files.
+
+	* configuration.cc, music/configuration.hh: New files.
+
+2007-10-23  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/setup.hh, setup.cc (setup::config_string): Renamed from
+	config_get_string.
+	(setup::config_int): Renamed from config_get_int.
+	(setup::config_double): Renamed from config_get_double.
+
+2007-10-19  Örjan Ekeberg  <orjan@nada.kth.se>
+
+	* music/runtime.hh, runtime.cc, music/setup.hh, setup.cc:
+	Replace C MPI calls to their equivalent C++ versions.
+
+2007-10-19  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music/setup.hh, setup.cc (setup::config_get_string,
+	setup::config_get_int, setup::config_get_double, setup::is_port,
+	setup::port_size): New methods.
+
+	* array_data.cc, music/array_data.hh: Renamed from arraydata.cc,
+	music/arraydata.hh.
+
+	* linear_index.cc, music/linear_index.hh: Renamed from
+	linearindex.cc, music/linearindex.hh.
+
+	* arraydata.cc, linearindex.cc, music/arraydata.hh,
+	music/linearindex.hh, music/setup.hh (array_data, linear_index):
+	Renamed from arraydata and linearindex everywhere.
+
+	* Makefile.am (libmusic_la_SOURCES): Added linear_index.cc,
+	music/linear_index.hh music/index_map.hh mysic/array_data.hh
+	array_data.cc music/array_data.hh.
+	(musicinclude_HEADERS): Added music/index_map.hh music/data_map.hh
+	music/linear_index.hh music/array_data.hh.
+
+2007-10-19  Örjan Ekeberg  <orjan@nada.kth.se>
+
+	* Makefile.am, music/arraydata.hh, music/data_map.hh,
+	music/index_map.hh, music/linearindex.hh, arraydata.cc,
+	linearindex.cc: Added abstraction classes for data indexing.
+
+	* music/setup.hh, setup.cc: Added publish method.
+	Add communicator access method (duplication from runtime).
+
+2007-09-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* runtime.cc, setup.cc: Rewritten.
+
+	* Makefile.am, music/setup.hh, music/runtime.hh: New files.
+
+	* music.hh: Rewritten to include header files under the music
+	directory.
+
+2007-08-17  orjan  <orjan@nada.kth.se>
+
+	* music.hh (MUSIC): Add binding routines
+
+2007-08-17  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Bong!
+
diff --git a/src/FIBO.cc b/src/FIBO.cc
new file mode 100644
index 0000000..02603f6
--- /dev/null
+++ b/src/FIBO.cc
@@ -0,0 +1,108 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <cstring>
+#include <iostream>
+#include "music/FIBO.hh"
+
+namespace MUSIC {
+
+  FIBO::FIBO (int es)
+  {
+    configure (es);
+  }
+
+  
+  void
+  FIBO::configure (int es)
+  {
+    elementSize = es;
+    size_ = elementSize * nInitial;
+    if (es > 0)
+      buffer.resize (size_);
+    current = 0;
+  }
+
+  
+  bool
+  FIBO::isEmpty ()
+  {
+    return current == 0;
+  }
+
+  
+  void*
+  FIBO::insert ()
+  {
+    if (current == size_)
+      grow (2 * size_);
+    // Here we use the assumption that vector memory is contiguous
+    // Josuttis says this is the intention of STL even though the
+    // first version of the report is not clear about this.
+    void* memory = static_cast<void*> (&buffer[current]);
+    current += elementSize;
+    return memory;
+  }
+  
+
+  void
+  FIBO::insert (void* elements, int n_elements)
+  {
+    int blockSize = elementSize * n_elements;
+    if (current + blockSize > size_)
+      grow (3 * (current + blockSize) / 2);
+    // Here we use the assumption that vector memory is contiguous
+    // Josuttis says this is the intention of STL even though the
+    // first version of the report is not clear about this.
+    void* memory = static_cast<void*> (&buffer[current]);
+    memcpy (memory, elements, blockSize);
+    current += blockSize;
+  }
+
+
+  void
+  FIBO::clear ()
+  {
+    current = 0;
+  }
+  
+
+  void
+  FIBO::nextBlockNoClear (void*& data, int& blockSize)
+  {
+
+    data = static_cast<void*> (&buffer[0]);
+    blockSize = current;
+  }
+
+
+  void
+  FIBO::nextBlock (void*& data, int& blockSize)
+  {
+    nextBlockNoClear (data, blockSize);
+    clear ();
+  }
+
+
+  void
+  FIBO::grow (int newSize)
+  {
+    size_ = newSize;
+    buffer.resize (size_);
+  }
+  
+}
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..9edf176
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,93 @@
+## Process this file with Automake to create Makefile.in
+
+ACLOCAL = $(top_srcdir)/aclocal.sh
+
+lib_LTLIBRARIES = libmusic.la libmusic-c.la
+
+libmusic_la_SOURCES = \
+	runtime.cc music/runtime.hh \
+	setup.cc music/setup.hh \
+	error.cc music/error.hh music/debug.hh \
+	linear_index.cc music/linear_index.hh \
+	index_map.cc music/index_map.hh \
+	music/data_map.hh \
+	array_data.cc music/array_data.hh \
+	configuration.cc music/configuration.hh \
+	application_map.cc music/application_map.hh \
+	application_mapper.cc music/application_mapper.hh \
+	ioutils.cc music/ioutils.hh \
+	connectivity.cc music/connectivity.hh \
+	spatial.cc music/spatial.hh \
+	music/application_graph.hh \
+	temporal.cc music/temporal.hh \
+	parse.cc music/parse.hh \
+	port.cc music/port.hh \
+	sampler.cc music/sampler.hh \
+	event_router.cc music/event_router.hh \
+	event_routing_map.cc music/event_routing_map.hh \
+	distributor.cc music/distributor.hh \
+	collector.cc music/collector.hh \
+	clock.cc music/clock.hh \
+	subconnector.cc music/subconnector.hh \
+	connector.cc music/connector.hh \
+	multibuffer.cc music/multibuffer.hh \
+	connection.cc music/connection.hh \
+	permutation_index.cc music/permutation_index.hh \
+	index_map_factory.cc music/index_map_factory.hh \
+	scheduler_agent.cc music/scheduler_agent.hh \
+	scheduler.cc music/scheduler.hh \
+	BIFO.cc music/BIFO.hh \
+	FIBO.cc music/FIBO.hh music/message.hh \
+	interval.cc music/interval.hh music/interval_tree.hh \
+	music/interval_table.hh music/ordered_ilist.hh \
+	music/communication.hh music/memory.hh memory.cc \
+	music/predict_rank.hh predict_rank.cc \
+	music/version.hh version.cc 
+
+libmusic_la_HEADERS = music.hh
+libmusic_la_CXXFLAGS = -I$(top_srcdir) @MPI_CXXFLAGS@
+libmusic_la_LDFLAGS = $(top_builddir)/mpidep/libmpidep.la $(top_builddir)/rudeconfig/librudeconfig.la \
+	-version-info 1:0:0 -export-dynamic -Wl,-z,defs @MPI_LDFLAGS@
+libmusic_ladir = $(includedir)
+
+libmusic_c_la_SOURCES = \
+	music-c.cc music-c-c.c music-c.h \
+	predict_rank-c.cc
+
+libmusic_c_la_HEADERS = music-c.h  music/predict_rank-c.h
+libmusic_c_la_CXXFLAGS = -DBUILDING_MUSIC_LIBRARY @MPI_CXXFLAGS@
+libmusic_c_la_CFLAGS = -DBUILDING_MUSIC_LIBRARY @MPI_CFLAGS@
+libmusic_c_la_LDFLAGS = \
+	-version-info 1:0:0 -export-dynamic -Wl,-z,defs \
+	$(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+libmusic_c_ladir = $(includedir)
+libmusic_c_la_DEPENDENCIES = libmusic.la
+
+musicincludedir = $(includedir)/music
+musicinclude_HEADERS = music/runtime.hh music/setup.hh \
+		       music/interval.hh music/interval_tree.hh \
+		       music/interval_table.hh music/ordered_ilist.hh \
+		       music/index_map.hh music/data_map.hh \
+		       music/linear_index.hh music/array_data.hh \
+		       music/configuration.hh music/connectivity.hh \
+		       music/application_map.hh music/ioutils.hh \
+		       music/application_mapper.hh \
+		       music/application_graph.hh \
+		       music/spatial.hh music/temporal.hh music/error.hh \
+		       music/debug.hh music/port.hh music/clock.hh \
+		       music/connector.hh music/subconnector.hh \
+		       music/connection.hh music/multibuffer.hh \
+		       music/permutation_index.hh \
+		       music/scheduler_agent.hh music/scheduler.hh \
+		       music/index_map_factory.hh \
+		       music/sampler.hh music/BIFO.hh \
+		       music/FIBO.hh music/event_router.hh \
+		       music/event_routing_map.hh \
+		       music/collector.hh music/distributor.hh \
+		       music/cont_data.hh music/event.hh \
+		       music/message.hh music/music-config.hh \
+		       music/predict_rank.hh  music/predict_rank-c.h \
+		       music/communication.hh music/version.hh \
+		       music/memory.hh 
+
+MKDEP = gcc -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
diff --git a/src/application_map.cc b/src/application_map.cc
new file mode 100644
index 0000000..515fef7
--- /dev/null
+++ b/src/application_map.cc
@@ -0,0 +1,160 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "music/application_map.hh"
+#if MUSIC_USE_MPI
+  #include <mpi.h>
+#endif
+#include "music/ioutils.hh"
+#include <iostream>
+#include <fstream>
+namespace MUSIC {
+
+  ApplicationMap::ApplicationMap ()
+  {
+  }
+
+  int
+  ApplicationMap::nProcesses ()
+  {
+    int n = 0;
+    for (ApplicationMap::iterator i = begin (); i != end (); ++i)
+      n += i->nProc ();
+    return n;
+  }
+  
+  
+  ApplicationInfo*
+  ApplicationMap::lookup (std::string appName)
+  {
+    for (iterator i = begin (); i != end (); ++i)
+      {
+	if (i->name () == appName)
+	  return &*i;
+      }
+    return 0;
+  }
+
+
+  void
+  ApplicationMap::add (std::string name, int n, int c)
+  {
+    push_back (ApplicationInfo (name, n, c));
+  }
+
+  
+  void
+  ApplicationMap::write (std::ostringstream& out)
+  {
+	  out << size ();
+	  for (iterator i = begin (); i != end (); ++i)
+	  {
+		  out << ':';
+		  IOUtils::write (out, i->name ());
+		  out << ':' << i->nProc ();
+	  }
+  }
+
+
+  void
+  ApplicationMap::read (std::istringstream& in)
+  {
+    int nApp;
+    in >> nApp;
+
+#ifdef MUSIC_DEBUG
+    /*  for debugging */
+    std::ofstream outfile ("leaders");
+#endif
+    for (int i = 0; i < nApp; ++i)
+      {
+        in.ignore ();
+        std::string name = IOUtils::read (in);
+        in.ignore ();
+        int np;
+        in >> np;
+#ifdef MUSIC_DEBUG
+        /*  for debugging */
+        outfile<< name << "\t" << aleader << std::endl;
+#endif
+        add (name, np, i);
+      }
+#ifdef MUSIC_DEBUG
+    /*  for debugging */
+    outfile.close();
+#endif
+  }
+
+
+  ApplicationInfo*
+  ApplicationMap::lookup (int color)
+  {
+    for (iterator i = begin (); i != end (); ++i)
+      {
+        if (i->color () == color)
+          return &*i;
+      }
+    return 0;
+
+  }
+
+#if MUSIC_USE_MPI
+  std::map<int, int>
+  ApplicationMap::assignLeaders (std::string my_app_label)
+  {
+    std::map<int, int> leaders;
+
+    int size = MPI::COMM_WORLD.Get_size ();
+    int my_rank = MPI::COMM_WORLD.Get_rank ();
+    int *colors = new int[size];
+    colors[my_rank] = lookup (my_app_label)->color ();
+    MPI::COMM_WORLD.Allgather (MPI::IN_PLACE, 0, MPI::INT, colors, 1, MPI::INT);
+
+    int prev_color = -1;
+    for (int i = 0; i < size; ++i)
+      {
+        if (colors[i] != prev_color)
+          {
+            ApplicationInfo* info = lookup (colors[i]);
+            info->setLeader (i);
+            leaders[info->color ()] = i;
+            prev_color = colors[i];
+          }
+      }
+
+#ifdef MUSIC_DEBUG
+    /*  block for debugging */
+    std::ofstream outfile ("ranks");
+    for(int i = 0; i < nLeaders; ++i)
+      {
+        outfile<< i <<":";
+        for(int j = 0; j < gsize; ++j)
+        if(rbuf[j] == i) outfile<< " " << j;
+        outfile<<std::endl;
+      }
+    outfile<<std::endl;
+    outfile.close();
+    /*end of block */
+#endif // MUSIC_DEBUG
+    delete[] colors;
+    return leaders;
+  }
+#endif
+}
+
diff --git a/src/application_mapper.cc b/src/application_mapper.cc
new file mode 100644
index 0000000..0ea3dba
--- /dev/null
+++ b/src/application_mapper.cc
@@ -0,0 +1,409 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/music-config.hh"
+
+#include "music/debug.hh"
+
+#include "music/error.hh"
+#include <iostream>
+#include <fstream>
+#include <stdlib.h>
+#include <string>
+#include <algorithm>
+#include <assert.h>
+#include "music/application_mapper.hh"
+
+#include "rudeconfig/src/config.h"
+
+#if MUSIC_USE_MPI
+  #include <mpi.h>
+#endif
+
+#if HAVE_SYS_STAT_H
+  #include <sys/stat.h>
+#endif
+
+namespace MUSIC {
+
+
+  // This is where we parse the configuration file
+  // NOTE: Could check here that obligatory parameters exists
+
+  ApplicationMapper::ApplicationMapper (Configuration *config)
+  {
+    config_ = config;
+    applications_ = config->applications();
+    connectivityMap_ = config->connectivityMap();
+    cfile_ = new rude::Config ();
+    app_selector_ = NULL;
+  }
+
+
+  ApplicationMapper::~ApplicationMapper()
+  {
+    if (app_selector_ != NULL)
+      delete app_selector_;
+    delete cfile_;
+  }
+
+
+  Configuration*
+  ApplicationMapper::map (std::istream* configFile, int rank)
+  {
+    MUSIC_LOG("Co-simulation launched using music utility");
+    app_selector_ = new SelectorR (rank);
+    map (configFile);
+    return config_;
+  }
+
+
+#if MUSIC_USE_MPI
+  Configuration*
+  ApplicationMapper::map (std::istream* configFile, std::string binary,
+      std::string appLabel)
+  {
+
+    //how do we identify ourselves
+    if (appLabel.length () != 0)
+      {
+        MUSIC_LOG("MPMD launch with --app-label option:" << appLabel);
+        app_selector_ = new SelectorOp (appLabel);
+      }
+    else
+      {
+
+        int my_rank = MPI::COMM_WORLD.Get_rank ();
+        int nRanks = MPI::COMM_WORLD.Get_size ();
+
+#if HAVE_SYS_STAT_H
+
+        long my_ino = ApplicationMapper::getApplicationINO (binary.c_str ());
+        // communicate st.st_ino
+        long *inos = new long[nRanks];
+        inos[my_rank] = my_ino;
+        MPI::COMM_WORLD.Allgather (MPI::IN_PLACE, 0, MPI::LONG, inos, 1,
+            MPI::LONG);
+
+        int index = 0;
+        int i = 0;
+        // among processors with the same ino number
+        // assign current sequential order number.
+        while (i < my_rank)
+          if (inos[i++] == my_ino)
+            index++;
+        delete[] inos;
+
+        MUSIC_LOG("MPMD launch. Application INO:" << my_ino);
+        app_selector_ = new SelectorINO (my_ino, index);
+#else
+        std::ostringstream oss;
+        oss << "MUSIC: HAVE_SYS_STAT_H is node defined, use --app-label to specify application label";
+        error0 (oss.str ());
+#endif
+
+      }
+    map (configFile);
+    return config_;
+  }
+#endif
+
+void
+  ApplicationMapper::map (std::istream* configFile)
+  {
+
+    if (cfile_->load (*configFile))
+      {
+        bool leader_avail = false;
+        mapApplications ();
+#if MUSIC_USE_MPI
+        if (MPI::Is_initialized ())
+          {
+            applications_->assignLeaders (config_->Name ());
+            leader_avail = true;
+          }
+#endif
+        mapConnectivity (leader_avail);
+      }
+    else
+      error0 ("Configuration file load: " + std::string (cfile_->getError ()));
+  }
+
+
+  void
+  ApplicationMapper::mapApplications ()
+  {
+
+    // retrieve default configurations for current object config_
+    mapSection ( 0, config_->defaultConfig());
+
+    // create temporal object with the default configurations
+    Configuration *config = new Configuration ();
+    config->defaultConfig ()->setDict(config_->defaultConfig ()->getDict ());
+
+    int n_selections = 0;
+    int np;
+    int nSections = cfile_->getNumSections ();
+    // loop through all sections
+    for (int s = 1; s < nSections; ++s)
+      {
+        // retrieve configuration to the temporal object
+        mapSection (s, config);
+
+        // if retrieved section is current configuration
+        if (app_selector_->selected(config))
+          {
+            ++n_selections;
+            // copy configuration settings to current object
+            config_->setDict (config->getDict ());
+
+            config_->setName(config->Name());
+
+          }
+
+        // save application information
+        config->lookup ("np", &np);
+        applications_->add (config->Name(), np, s - 1);
+        // empty temporal object
+        // NOTE: default configuration is preserved
+        config->resetDict();
+      }
+    delete config;
+    assert(config_->getDict().size() != 0);
+
+    // NOTE: given rank -1 causes an assertion failure
+    assert(n_selections == 1);
+  }
+
+
+  void
+  ApplicationMapper::mapSection (int index, Configuration* config)
+  {
+    std::string name (cfile_->getSectionNameAt (index));
+    cfile_->setSection (name.c_str ());
+    int nMembers = cfile_->getNumDataMembers ();
+    config->setName(name);
+    for (int m = 0; m < nMembers; ++m)
+      {
+        std::string n (cfile_->getDataNameAt (m));
+        std::string v (cfile_->getStringValue (n.c_str ()));
+        config->insert (n,  v);
+      }
+  }
+
+
+  void
+  ApplicationMapper::mapConnectivity (bool leaders)
+  {
+
+    std::map<std::string, int> receiverPortCodes;
+    int nextPortCode = 0;
+
+    int nSections = cfile_->getNumSections ();
+    for (int s = 0; s < nSections; ++s)
+      {
+        std::string secName (cfile_->getSectionNameAt (s));
+        cfile_->setSection (secName.c_str ());
+
+        int nConnections = cfile_->getNumSourceDestMembers ();
+        for (int c = 0; c < nConnections; ++c)
+          {
+            std::string senderApp (cfile_->getSrcAppAt (c));
+            std::string senderPort (cfile_->getSrcObjAt (c));
+            std::string receiverApp (cfile_->getDestAppAt (c));
+            std::string receiverPort (cfile_->getDestObjAt (c));
+            std::string width (cfile_->getWidthAt (c));
+            std::string commType (cfile_->getCommTypeAt (c));
+            std::string procMethod (cfile_->getProcMethodAt (c));
+
+            if (senderApp == "")
+              {
+                if (secName == "")
+                  error (
+                      "sender application not specified for output port "
+                          + senderPort);
+                else
+                  senderApp = secName;
+              }
+            if (receiverApp == "")
+              {
+                if (secName == "")
+                  error (
+                      "receiver application not specified for input port "
+                          + receiverPort);
+                else
+                  receiverApp = secName;
+              }
+            if (senderApp == receiverApp)
+              error (
+                  "port " + senderPort + " of application " + senderApp
+                      + " connected to the same application");
+
+
+            //  Communication type option can be either *point-to-point* or
+            // *collective* written in any case letters.
+            std::transform (commType.begin (), commType.end (),
+                commType.begin (), ::tolower);
+            if (commType.length () > 0 && commType.compare ("collective")
+                && commType.compare ("point-to-point"))
+              error ("communication type " + commType + " is not supported");
+
+            //  Processing method can be either *tree* or
+            // *table* written in any case letters.
+            std::transform (procMethod.begin (), procMethod.end (),
+                procMethod.begin (), ::tolower);
+            if (procMethod.length () > 0 && procMethod.compare ("table")
+                && procMethod.compare ("tree"))
+              error ("processing method " + procMethod + " is not supported");
+
+            // Generate a unique "port code" for each receiver port
+            // name.  This will later be used during temporal
+            // negotiation since it easier to communicate integers,
+            // which have constant size, than strings.
+            //
+            // NOTE: This code must be executed in the same order in
+            // all MPI processes.
+            std::string receiverPortFullName = receiverApp + "." + receiverPort;
+            std::map<std::string, int>::iterator pos = receiverPortCodes.find (
+                receiverPortFullName);
+            int portCode;
+            if (pos == receiverPortCodes.end ())
+              {
+                portCode = nextPortCode++;
+                receiverPortCodes.insert (
+                    std::make_pair (receiverPortFullName, portCode));
+              }
+            else
+              portCode = pos->second;
+
+            ConnectivityInfo::PortDirection dir;
+            ApplicationInfo* remoteInfo;
+            if (config_->Name () == senderApp)
+              {
+                dir = ConnectivityInfo::OUTPUT;
+                remoteInfo = applications_->lookup (receiverApp);
+              }
+            else if (config_->Name () == receiverApp)
+              {
+                dir = ConnectivityInfo::INPUT;
+                remoteInfo = applications_->lookup (senderApp);
+              }
+            else
+              continue;
+            int w;
+            if (width == "")
+              w = ConnectivityInfo::NO_WIDTH;
+            else
+              {
+                std::istringstream ws (width);
+                if (! (ws >> w))
+                  error ("could not interpret width");
+              }
+
+             // default communication type is *point-to-point*
+            int iCommType;
+            if (commType.length () == 0 || !commType.compare ("point-to-point"))
+                iCommType = ConnectorInfo::POINTTOPOINT;
+            else
+                iCommType = ConnectorInfo::COLLECTIVE;
+
+             // default processing method is *tree*
+            int iProcMethod;
+            if (procMethod.length () == 0 || !procMethod.compare ("tree"))
+                iProcMethod = ConnectorInfo::TREE;
+
+            else
+                iProcMethod = ConnectorInfo::TABLE;
+
+            // NOTE: leader number can be not available at this stage,
+            // if leader is not available, we write down the color of the application
+            int leader = leaders ? remoteInfo->leader () : remoteInfo->color ();
+            connectivityMap_->add (
+                dir == ConnectivityInfo::OUTPUT ? senderPort : receiverPort,
+                dir, w, receiverApp, receiverPort, portCode, leader,
+                remoteInfo->nProc (), iCommType, iProcMethod);
+          }
+      }
+  }
+
+
+#if HAVE_SYS_STAT_H
+  long
+  ApplicationMapper::getApplicationINO(const char * path)
+    {
+      struct stat st;
+      if (stat(path, &st) == -1)
+        {
+          std::ostringstream oss;
+          oss
+          << "MUSIC: Couldn't retrieve file status (stat()) about: " << path;
+          error0 (oss.str ());
+        }
+      return st.st_ino;
+    }
+#endif
+
+
+  bool
+  SelectorR::selected (Configuration* config)
+  {
+#if MUSIC_USE_MPI
+    int np;
+    config->lookup ("np", &np);
+    selected_ = rank_ < next_chunk_;
+    next_chunk_ += np;
+    return rank_ < next_chunk_ && !selected_;
+#endif
+
+    return false;
+  }
+
+
+  bool
+  SelectorOp::selected (Configuration* config)
+  {
+    std::string sec_name = config->Name();
+    return !app_label_.compare(sec_name);
+  }
+
+
+  bool
+  SelectorINO::selected (Configuration* config)
+  {
+#if HAVE_SYS_STAT_H
+    std::string sec_name;
+    config->lookup("appLabel", &sec_name);
+    std::string binary;
+    config->lookup("binary", &binary);
+    long ino = ApplicationMapper::getApplicationINO (binary.c_str());
+    if (ino == ino_)
+      {
+        int np;
+        config->lookup("np", &np);
+        selected_ = my_chunk_ < next_chunk_;
+        next_chunk_+=np;
+      }
+
+    return ino == ino_ && my_chunk_ < next_chunk_ && !selected_;
+#endif
+
+    return false;
+
+  }
+
+}
diff --git a/src/array_data.cc b/src/array_data.cc
new file mode 100644
index 0000000..1942b8b
--- /dev/null
+++ b/src/array_data.cc
@@ -0,0 +1,55 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// This header file needs to be included first since array_data.hh
+// includes <mpi.h> which musy be included first on BG/L
+#include "music/array_data.hh"
+#if MUSIC_USE_MPI
+
+#include "music/linear_index.hh"
+
+namespace MUSIC {
+  
+  ArrayData::ArrayData (void* buffer, MPI::Datatype type, IndexMap* map)
+    : DataMap (buffer), type_ (type), indexMap_ (map->copy ())
+  {
+  }
+
+  ArrayData::~ArrayData ()
+  {
+    delete indexMap_;
+  }
+  
+  ArrayData::ArrayData (void* buffer,
+			MPI::Datatype type,
+			int baseIndex,
+			int size)
+    : DataMap (buffer)
+  {
+    type_ = type;
+    indexMap_ = new LinearIndex (baseIndex, size);
+  }
+
+  DataMap*
+  ArrayData::copy ()
+  {
+    return new ArrayData (base (), type_, indexMap_);
+  }
+  
+}
+#endif
diff --git a/src/clock.cc b/src/clock.cc
new file mode 100644
index 0000000..06717fd
--- /dev/null
+++ b/src/clock.cc
@@ -0,0 +1,91 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "music/clock.hh"
+
+namespace MUSIC {
+
+  ClockState::ClockState (double t, double tb)
+  {
+    double dstate = t / tb;
+    if (dstate >= 0.0)
+      state = dstate + 0.5;
+    else
+      state = dstate - 0.5;
+  }
+
+  
+  ClockState
+  ClockState::Serialized::deserialize ()
+  {
+    return (static_cast<long long> (upper) << 32) | lower;
+  }
+
+
+  ClockState::Serialized
+  ClockState::serialize ()
+  {
+    Serialized s;
+    s.upper = (state >> 32);
+    s.lower = state & 0xffffffffLL;
+    return s;
+  }
+
+
+  Clock::Clock (double tb, double h)
+  {
+    configure (tb, ClockState (h, tb));
+  }
+
+
+  void
+  Clock::configure (double tb, ClockState ti)
+  {
+    state_ = 0;
+    timebase_ = tb;
+    tickInterval_ = ti;
+  }
+
+
+  void
+  Clock::reset ()
+  {
+    state_ = 0;
+  }
+
+
+  void
+  Clock::tick ()
+  {
+    state_ += tickInterval_;
+  }
+  
+
+  void
+  Clock::ticks (int n)
+  {
+    state_ += n * tickInterval_;
+  }
+  
+
+  double
+  Clock::time () const
+  {
+    return timebase_ * state_;
+  }
+  
+}
diff --git a/src/collector.cc b/src/collector.cc
new file mode 100644
index 0000000..134e2af
--- /dev/null
+++ b/src/collector.cc
@@ -0,0 +1,155 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/collector.hh"
+
+#include "music/debug.hh"
+
+#if MUSIC_USE_MPI
+// collector.hh needs to be included first since it causes inclusion
+// of mpi.h (in data_map.hh).  mpi.h must be included before other
+// header files on BG/L
+
+
+#include <algorithm>
+#include <cstring>
+
+#include "music/event.hh"
+
+namespace MUSIC {
+
+  Collector::Interval::Interval (IndexInterval& interval)
+  {
+    setBegin (interval.begin ());
+    setLength (interval.end () - interval.begin ());
+  }
+  
+
+  void
+  Collector::configure (DataMap* dmap, int maxsize)
+  {
+    dataMap = dmap;
+    maxsize_ = maxsize;
+  }
+  
+
+  IntervalTree<int, MUSIC::Interval, int>*
+  Collector::buildTree ()
+  {
+    IntervalTree<int, MUSIC::Interval, int>* tree
+      = new IntervalTree<int, MUSIC::Interval, int> ();
+    
+    IndexMap* indices = dataMap->indexMap ();
+    for (IndexMap::iterator i = indices->begin ();
+	 i != indices->end ();
+	 ++i)
+      {
+	MUSIC_LOGR ("adding (" << i->begin () << ", " << i->end ()
+		    << ", " << i->local () << ") to tree");
+	tree->add (*i, i->local ());
+      }
+
+    tree->build ();
+    
+    return tree;
+  }
+  
+
+  void
+  Collector::addRoutingInterval (IndexInterval interval, BIFO* buffer)
+  {
+    BufferMap::iterator b = buffers.find (buffer);
+    if (b == buffers.end ())
+      {
+	buffers.insert (std::make_pair (buffer, Intervals ()));
+	b = buffers.find (buffer);
+      }
+    Intervals& intervals = b->second;
+    intervals.push_back (Interval (interval));
+  }
+
+
+  void
+  Collector::IntervalCalculator::operator() (int& offset)
+  {
+    interval_.setBegin (elementSize_
+			* (interval_.begin () - offset));
+    interval_.setLength (elementSize_ * interval_.length ());
+  }
+
+
+  void
+  Collector::initialize ()
+  {
+    IntervalTree<int, MUSIC::Interval, int>* tree = buildTree ();
+    
+    for (BufferMap::iterator b = buffers.begin (); b != buffers.end (); ++b)
+      {
+	BIFO* buffer = b->first;
+	Intervals& intervals = b->second;
+	sort (intervals.begin (), intervals.end ());
+	int elementSize = dataMap->type ().Get_size ();
+	int size = 0;
+	for (Intervals::iterator i = intervals.begin ();
+	     i != intervals.end ();
+	     ++i)
+	  {
+	    IntervalCalculator calculator (*i, elementSize);
+	    MUSIC_LOGX ("searching for " << i->begin ());
+	    tree->search (i->begin (), &calculator);
+	    size += i->length ();
+	  }
+	buffer->configure (size, maxsize_);
+      }
+  }
+
+
+  void
+  Collector::collect (ContDataT* base)
+  {
+	ContDataT* dest = static_cast<ContDataT*> (base);
+    for (BufferMap::iterator b = buffers.begin (); b != buffers.end (); ++b)
+      {
+	BIFO* buffer = b->first;
+	Intervals& intervals = b->second;
+	ContDataT* src = static_cast<ContDataT*> (buffer->next ());
+	if (src == NULL)
+	  // Out of data (remote has flushed)
+	  return;
+	for (Intervals::iterator i = intervals.begin ();
+	     i != intervals.end ();
+	     ++i)
+	  {
+	    MUSIC_LOGX ("collect to dest = " << static_cast<void*> (dest)
+		       << ", begin = " << i->begin ()
+		       << ", length = " << i->length ());
+
+	    memcpy (dest + i->begin (), src, i->length ());
+	    src += i->length ();
+	  }
+      }
+  }
+
+  void
+  Collector::collect ()
+  {
+    collect (static_cast<ContDataT*> (dataMap->base ()));
+  }
+
+}
+#endif
diff --git a/src/configuration.cc b/src/configuration.cc
new file mode 100644
index 0000000..74654b7
--- /dev/null
+++ b/src/configuration.cc
@@ -0,0 +1,314 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009, 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/configuration.hh" // Must be included first on BG/L
+
+#include "music/debug.hh"
+
+extern "C" {
+#include <stdlib.h>
+}
+
+#include "music/ioutils.hh"
+#include "music/error.hh"
+#include <iostream>
+#include <fstream>
+
+namespace MUSIC {
+
+  const char* const Configuration::configEnvVarName = "_MUSIC_CONFIG_";
+ // const char* const Configuration::mapFileName = "music.map";
+
+  /*
+   * This is the syntax of the _MUSIC_CONFIG_ variable:
+   *
+   * POSTPONE:COLOR means that configuration is postponed until the
+   * first port is created.  At this time, the variable is expected to
+   * contain the full configuration information:
+   *
+   *
+   * APPLICATIONNAME:COLOR:APPLICATIONMAP:CONNECTIVITYMAP:CONFIGDICT
+   *
+   * APPLICATIONNAME = name of this application (string)
+   *
+   * COLOR = index of section in music configuration file
+   *
+   * APPLICATIONMAP = SIZE:...:NAMEk:NPROCk:...
+   *
+   * SIZE = number of applications (integer)
+   *
+   * NAMEk = name of application k
+   *
+   * NPROCk = number of processes in application k
+   *
+   * CONNECTIVITYMAP = SIZE:...:PORTNAMEk:DIRECTIONk:WIDTHk:CONNECTIONSk:...
+   *
+   * SIZE = number of ports of this application
+   *
+   * PORTNAMEk = port name
+   *
+   * DIRECTIONk = port direction, 0 = OUTPUT, 1 = INPUT
+   *
+   * WIDTHk = port width
+   *
+   * CONNECTIONSk = SIZE:...:
+   *                RECAPPNAME:RECPORTNAME:RECPORTCODE:REMOTELEADER:NREMOTEPROCS
+   *                :COMMTYPE:PROCMETHOD:...
+   *
+   * RECAPPNAME = name of receiving application
+   *
+   * RECPORTNAME = name of receiver port
+   *
+   * RECPORTCODE = code unique for every receiver port
+   *
+   * REMOTELEADER = lowest rank of the remote application
+   *
+   * NREMOTEPROCS = number of processes in the remote application
+   *
+   * COMMTYPE = communication algorithm, 0 = collective, 1 = point-to-point
+   *
+   * PROCMETHOD = processing method, 0 = tree, 1 = table
+   *
+   * CONFIGDICT = ...:VARNAMEk=VALUEk:...
+   */
+
+  Configuration::Configuration ()
+  {
+    init ();
+  }
+
+#if MUSIC_USE_MPI
+  Configuration::Configuration (std::string configStr)
+  {
+    init ();
+    parse (configStr);
+  }
+#endif
+
+  Configuration::~Configuration ()
+  {
+    delete connectivityMap_;
+    delete applications_;
+    if (defaultConfig_ != NULL)
+      delete defaultConfig_;
+  }
+
+
+  void
+  Configuration::init ()
+  {
+    applications_ = new ApplicationMap ();
+    connectivityMap_ = new Connectivity ();
+    defaultConfig_ = NULL;
+  }
+
+#if MUSIC_USE_MPI
+  void
+  Configuration::parse(std::string configStr)
+  {
+    std::istringstream env (configStr);
+    setName (IOUtils::read (env));
+    env.ignore ();
+    // do not need color information,
+    // but we can use for error check
+    env.ignore ();
+    env.ignore ();
+    applications_->read (env);
+    env.ignore ();
+    std::map<int, int> leaders = applications_->assignLeaders( Name ());
+    connectivityMap_->read (env, leaders);
+    // parse config string
+    while (!env.eof ())
+      {
+        env.ignore ();
+        std::string name = IOUtils::read (env, '=');
+        env.ignore ();
+        std::string v = IOUtils::read (env);
+      //  std::cerr << name << " " << v << std::endl;
+        insert (name, v );
+      }
+
+  }
+#endif
+
+  void
+  Configuration::write (std::ostringstream& env, Configuration* mask)
+  {
+    std::map<std::string, std::string>::iterator pos;
+    for (pos = dict_.begin (); pos != dict_.end (); ++pos)
+      {
+	std::string name = pos->first;
+	if (!(mask && mask->lookup (name)))
+	  {
+	    env << ':' << name << '=';
+	    IOUtils::write (env, pos->second);
+	  }
+      }
+  }
+
+
+  void
+  Configuration::writeEnv ()
+  {
+    std::ostringstream env;
+    env << Name () << ':' << Color () << ':';
+    applications_->write (env);
+    env << ':';
+    connectivityMap_->write (env);
+    write (env, 0);
+    if (defaultConfig_ != NULL)
+      defaultConfig_->write (env, this);
+    setenv (configEnvVarName, env.str ().c_str (), 1);
+  }
+
+
+  bool
+  Configuration::lookup(std::string name)
+  {
+    return dict_.find(name) != dict_.end();
+  }
+
+  bool
+  Configuration::lookup(std::string name, std::string* result)
+  {
+    std::map<std::string, std::string>::iterator pos = dict_.find(name);
+    if (pos == dict_.end())
+      return defaultConfig_ && defaultConfig_->lookup(name, result);
+
+    *result = pos->second;
+    return true;
+  }
+
+  bool
+  Configuration::lookup(std::string name, int* result)
+  {
+    std::map<std::string, std::string>::iterator pos = dict_.find(name);
+    if (pos == dict_.end())
+      return defaultConfig_ && defaultConfig_->lookup(name, result);
+
+    std::istringstream iss(pos->second);
+    if (! (iss >> *result).fail())
+      return true;
+
+    std::ostringstream oss;
+    oss << "var " << name << " given wrong type (" << pos->second
+	<< "; expected int) in config file";
+    error(oss.str());
+    return true; // Doesn't happen! Just for compiler!
+  }
+
+  bool
+  Configuration::lookup(std::string name, double* result)
+  {
+    std::map<std::string, std::string>::iterator pos = dict_.find(name);
+    if (pos == dict_.end())
+      return defaultConfig_ && defaultConfig_->lookup (name, result);
+
+    std::istringstream iss(pos->second);
+    if (! (iss >> *result).fail())
+      return true;
+
+    std::ostringstream oss;
+    oss << "var " << name << " given wrong type (" << pos->second
+	<< "; expected double) in config file";
+    error(oss.str());
+    return true; // Doesn't happen! Just for compiler!
+  }
+
+  std::string
+  Configuration::Name ()
+  {
+    return app_name_;
+  }
+
+
+  void
+  Configuration::setName (std::string app_name)
+  {
+    app_name_ = app_name;
+  }
+
+
+  int
+  Configuration::Color()
+  {
+    return applications_->lookup (app_name_)->color ();
+  }
+
+
+  int
+  Configuration::Leader()
+  {
+    ApplicationInfo* info = applications_->lookup (app_name_);
+    return info == 0 ? -1 : info->leader ();
+  }
+
+
+  void
+  Configuration::insert (std::string name, std::string value)
+  {
+
+    dict_.insert (std::make_pair (name, value));
+  }
+
+
+  ApplicationMap*
+  Configuration::applications ()
+  {
+    return applications_;
+  }
+
+
+  Configuration*
+  Configuration::defaultConfig ()
+  {
+    if (defaultConfig_ == NULL)
+      defaultConfig_ = new Configuration();
+    return defaultConfig_;
+  }
+
+
+  Connectivity*
+  Configuration::connectivityMap ()
+  {
+    return connectivityMap_;
+  }
+
+
+  const Configuration::ConfigDict &
+  Configuration::getDict()
+  {
+    return dict_;
+  }
+
+
+  void
+  Configuration::setDict(const Configuration::ConfigDict &dict)
+  {
+    dict_ = dict;
+
+  }
+
+
+  void
+  Configuration::resetDict()
+  {
+    dict_ = Configuration::ConfigDict ();
+  }
+
+}
diff --git a/src/connection.cc b/src/connection.cc
new file mode 100644
index 0000000..ae60179
--- /dev/null
+++ b/src/connection.cc
@@ -0,0 +1,47 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "music/connection.hh"
+
+#if MUSIC_USE_MPI
+
+
+namespace MUSIC {
+
+  OutputConnection::OutputConnection (Connector* connector,
+				      int maxBuffered,
+				      int elementSize)
+    : Connection (connector, maxBuffered),
+      elementSize_ (elementSize)
+  {
+
+  }
+
+  InputConnection::InputConnection (Connector* connector,
+				    int maxBuffered,
+				    ClockState accLatency,
+				    bool interpolate)
+    : Connection (connector, maxBuffered),
+      accLatency_ (accLatency),
+      interpolate_ (interpolate)
+
+  {
+  }
+
+  
+}
+#endif
diff --git a/src/connectivity.cc b/src/connectivity.cc
new file mode 100644
index 0000000..963ffe7
--- /dev/null
+++ b/src/connectivity.cc
@@ -0,0 +1,243 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009, 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <algorithm>
+
+#include "music/music-config.hh"
+
+#include "music/debug.hh"
+
+#include "music/connectivity.hh"
+#include "music/ioutils.hh"
+#include "music/error.hh"
+
+namespace MUSIC {
+
+  int ConnectorInfo::maxPortCode_;
+
+  void
+  ConnectorInfo::registerPortCode (int portCode)
+  {
+    ConnectorInfo::maxPortCode_ = std::max (portCode,
+					    ConnectorInfo::maxPortCode_);
+  }
+
+
+  void
+  ConnectivityInfo::addConnection (std::string recApp,
+				   std::string recName,
+				   int recCode,
+				   int rLeader,
+				   int nProc,
+				   int commType,
+				   int procMethod
+					)
+  {
+    portConnections_.push_back (ConnectorInfo (recApp,
+					       recName,
+					       recCode,
+					       rLeader,
+					       nProc,
+					       commType,
+					       procMethod));
+  }
+
+
+  void
+  Connectivity::add (std::string localPort,
+		     ConnectivityInfo::PortDirection dir,
+		     int width,
+		     std::string recApp,
+		     std::string recPort,
+		     int recPortCode,
+		     int remoteLeader,
+		     int remoteNProc,
+		     int commType,
+			 int procMethod
+				)
+  {
+    std::map<std::string, int>::iterator cmapInfo
+      = connectivityMap.find (localPort);
+    ConnectivityInfo* info;
+    if (cmapInfo == connectivityMap.end ())
+      {
+	MUSIC_LOG ("creating new entry for " << localPort);
+	int index = connections_.size ();
+	connections_.push_back (ConnectivityInfo (localPort, dir, width));
+	info = &connections_.back ();
+	MUSIC_LOG ("ci = " << info);
+	connectivityMap.insert (std::make_pair (localPort, index));
+      }
+    else
+      {
+	MUSIC_LOG ("found old entry for " << localPort);
+	info = &connections_[cmapInfo->second];
+	if (info->direction () != dir)
+	  error ("port " + localPort + " used both as output and input");
+      }
+    info->addConnection (recApp,
+			 recPort,
+			 recPortCode,
+			 remoteLeader,
+			 remoteNProc,
+			 commType,
+			 procMethod
+				);
+  }
+
+
+  ConnectivityInfo*
+  Connectivity::info (std::string portName)
+  {
+    std::map<std::string, int>::iterator info
+      = connectivityMap.find (portName);
+    if (info == connectivityMap.end ())
+      return NO_CONNECTIVITY;
+    else
+      return &connections_[info->second];
+  }
+
+
+  bool
+  Connectivity::isConnected (std::string portName)
+  {
+    return connectivityMap.find (portName) != connectivityMap.end ();
+  }
+
+
+  ConnectivityInfo::PortDirection
+  Connectivity::direction (std::string portName)
+  {
+    return connections_[connectivityMap[portName]].direction ();
+  }
+
+  
+  int
+  Connectivity::width (std::string portName)
+  {
+    return connections_[connectivityMap[portName]].width ();
+  }
+
+  
+  PortConnectorInfo
+  Connectivity::connections (std::string portName)
+  {
+    return connections_[connectivityMap[portName]].connections ();
+  }
+
+
+  void
+  Connectivity::write (std::ostringstream& out)
+  {
+    out << connectivityMap.size ();
+    std::map<std::string, int>::iterator i;
+    for (i = connectivityMap.begin ();
+	 i != connectivityMap.end ();
+	 ++i)
+      {
+	out << ':' << i->first << ':';
+	ConnectivityInfo* ci = &connections_[i->second];
+	out << ci->direction () << ':' << ci->width () << ':';
+	PortConnectorInfo conns = ci->connections ();
+	out << conns.size ();
+	PortConnectorInfo::iterator c;
+	for (c = conns.begin (); c != conns.end (); ++c)
+	  {
+	    out << ':' << c->receiverAppName ();
+	    out << ':' << c->receiverPortName ();
+	    out << ':' << c->receiverPortCode ();
+	    out << ':' << c->remoteLeader ();
+	    out << ':' << c->nProcesses ();
+	    out << ':' << c->communicationType();
+	    out << ':' << c->processingMethod();
+	  }
+      }
+  }
+  
+
+  void
+  Connectivity::read (std::istringstream& in, std::map<int, int> leaders)
+  {
+    int nPorts;
+    in >> nPorts;
+    for (int i = 0; i < nPorts; ++i)
+      {
+	in.ignore ();
+	std::string portName = IOUtils::read (in);
+	in.ignore ();
+	int dir;
+	in >> dir;
+	ConnectivityInfo::PortDirection pdir
+	  = static_cast<ConnectivityInfo::PortDirection> (dir);
+	in.ignore ();
+	int width;
+	in >> width;
+	in.ignore ();
+	int nConnections;
+	in >> nConnections;
+	for (int i = 0; i < nConnections; ++i)
+	  {
+	    in.ignore ();
+	    std::string recApp = IOUtils::read (in);
+	    in.ignore ();
+	    std::string recPort = IOUtils::read (in);
+	    in.ignore ();
+	    int recPortCode;
+	    in >> recPortCode;
+	    ConnectorInfo::registerPortCode (recPortCode);
+	    in.ignore ();
+	    // leader information is not available through configuration string
+	    // application color is used instead
+	    int color;
+	    in >> color;
+	    in.ignore ();
+	    int nProc;
+	    in >> nProc;
+	    in.ignore ();
+	    int commType;
+	    in >> commType;
+	    in.ignore ();
+	    int procMethod;
+	    in >> procMethod;
+	    add (portName,
+		 pdir,
+		 width,
+		 recApp,
+		 recPort,
+		 recPortCode,
+		 leaders[color],
+		 nProc,
+		 commType,
+		 procMethod
+		 );
+	    MUSIC_LOG ("add (portName = " << portName
+		       << ", pdir = " << pdir
+		       << ", width = " << width
+		       << ", recApp = " << recApp
+		       << ", recPort = " << recPort
+		       << ", rLeader = " << leaders[color]
+		       << ", nProc = " << nProc
+		       << ", commType = " << commType
+		       << ", procMethod = " << procMethod
+		       << ")");
+	  }
+      }
+  }
+
+  
+}
diff --git a/src/connector.cc b/src/connector.cc
new file mode 100644
index 0000000..b7921b3
--- /dev/null
+++ b/src/connector.cc
@@ -0,0 +1,1115 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/connector.hh"
+
+#include "music/debug.hh"
+
+#if MUSIC_USE_MPI
+// connector.hh needs to be included first since it causes inclusion
+// of mpi.h (in data_map.hh).  mpi.h must be included before other
+// header files on BG/L
+#include "music/error.hh"
+#include "music/communication.hh"
+#include "music/event_router.hh"
+#include <cmath>
+#include <map>
+
+namespace MUSIC {
+  std::map<unsigned int, Connector*> Connector::flagMap_;
+
+  unsigned int Connector::nextFlag_ = 1;
+
+  unsigned int Connector::nextProxyFlag_ = 1;
+
+  Connector::Connector (ConnectorInfo info_,
+			IndexMap* indices,
+			Index::Type type,
+			MPI::Intracomm c)
+    : info (info_),
+      indices_ (indices->copy()),
+      type_ (type),
+      comm (c),
+      idFlag_ (0),
+      finalized_ (false)
+  {
+  }
+
+
+  Connector::Connector (ConnectorInfo info_,
+			IndexMap* indices,
+			Index::Type type,
+			MPI::Intracomm c,
+			MPI::Intercomm ic)
+    : info (info_),
+      indices_ (indices->copy()),
+      type_ (type),
+      comm (c),
+      intercomm (ic),
+      idFlag_ (0),
+      finalized_ (false)
+  {
+  }
+
+
+  bool
+  Connector::isLeader ()
+  {
+    return comm.Get_rank () == 0;
+  }
+
+  
+  void
+  Connector::createIntercomm ()
+  {
+
+    intercomm = comm.Create_intercomm (0,
+				       MPI::COMM_WORLD,
+				       info.remoteLeader (),
+				       CREATE_INTERCOMM_MSG);
+  }
+
+
+  void
+  Connector::freeIntercomm ()
+  {
+    intercomm.Free ();
+  }
+
+
+  void Connector::spatialNegotiation ()
+  {
+    SpatialNegotiator *spatialNegotiator_ = createSpatialNegotiator ();
+    width_ = spatialNegotiator_->getWidth ();
+    maxLocalWidth_ = spatialNegotiator_->maxLocalWidth ();
+    spatialNegotiation (spatialNegotiator_);
+    delete spatialNegotiator_;
+    delete indices_;
+  }
+
+
+  void Connector::spatialNegotiation (SpatialNegotiator * spatialNegotiator_)
+  {
+
+    if (spatialNegotiator_ == NULL)
+      error ("spatialNegotiator was not initialized");
+    std::map<int, Subconnector*> subconnectors;
+    NegotiationIterator i
+      = spatialNegotiator_->negotiate (info.nProcesses (),
+				       this); // only for debugging
+
+    for (	 ;!i.end ();	 ++i)
+      {
+  	std::map<int, Subconnector*>::iterator c
+  	  = subconnectors.find (i->rank ());
+  	Subconnector* subconn;
+  	if (c != subconnectors.end ())
+  	  subconn = c->second;
+  	else
+  	  {
+  	    subconn = makeSubconnector (i->rank ());
+  	    if(subconn == NULL)
+	      error ("Subconnector was not initialized");
+  	    subconnectors.insert (std::make_pair (i->rank (), subconn));
+  	    rsubconn.push_back (subconn);
+
+  	  }
+  	MUSIC_LOG (MPI::COMM_WORLD.Get_rank ()
+  		   << ": ("
+  		   << i->begin () << ", "
+  		   << i->end () << ", "
+  		   << i->local () << ", "
+  		   << i->displ() << ") -> " << i->rank ());
+  	addRoutingInterval (i->interval (), subconn);
+
+
+      }
+
+  }
+
+
+  // The following ordering of subconnectors leads to a reasonably
+  // efficient communication schedule where the number of
+  // communications that weill have to happen sequentially is O(P)
+  // where P is the number of processors.
+  //
+  // Mikael Djurfeldt et al. (2005) "Massively parallel simulation
+  // of brain-scale neuronal network models." Tech. Rep.
+  // TRITA-NA-P0513, CSC, KTH, Stockholm.
+
+  bool
+  lessInputSubconnector (const Subconnector* c1, const Subconnector* c2)
+  {
+    return (c1->remoteRank () < c2->remoteRank ()
+  	    || (c1->remoteRank () == c2->remoteRank ()
+  		&& c1->receiverPortCode () < c2->receiverPortCode ()));
+  }
+
+
+  bool
+  lessOutputSubconnector (const Subconnector* c1, const Subconnector* c2)
+  {
+    if ((c1->remoteRank () > c1->localRank ()
+	 && c2->remoteRank () <= c1->localRank ())
+	|| (c1->remoteRank () <= c1->localRank ()
+	    && c2->remoteRank () > c1->localRank ()))
+      return c1->remoteRank () > c2->remoteRank ();
+    else
+      return lessInputSubconnector (c1, c2);
+  }
+
+
+  void Connector::initialize ()
+  {
+    sort (rsubconn.begin (),
+	  rsubconn.end (),
+	  isInput () ? lessInputSubconnector : lessOutputSubconnector);
+  }
+
+
+  void
+  Connector::finalize ()
+  {
+    bool dataStillFlowing = false;
+    for (std::vector<Subconnector*>::iterator s = rsubconn.begin (); 	 s != rsubconn.end ();  	 ++s)
+      (*s)->flush(dataStillFlowing);
+    finalized_ = !dataStillFlowing;
+  }
+
+
+  void Connector::tick ()
+  {
+    for (std::vector<Subconnector*>::iterator s = rsubconn.begin ();	 s != rsubconn.end ();
+	 ++s){
+      (*s)->maybeCommunicate();
+    }
+  }
+
+
+  SpatialNegotiator *
+  OutputConnector::createSpatialNegotiator ()
+  {
+    return new SpatialOutputNegotiator(indices_, type_, comm, intercomm );
+  }
+
+#if MUSIC_ISENDWAITALL
+  void
+  OutputConnector::tick ()
+  {
+	  std::vector<MPI::Request>requests;
+	  for (std::vector<Subconnector*>::iterator s = rsubconn.begin ();	 s != rsubconn.end ();
+			  ++s){
+		  (*s)->maybeCommunicate(requests);
+	  }
+	  //The spec  guarantees vectors store their elements contiguously:
+	  MPI::Request::Waitall(requests.size(),  (MPI::Request *)&requests[0]);
+  }
+#endif //MUSIC_ISENDWAITALL
+
+  SpatialNegotiator *
+  InputConnector::createSpatialNegotiator ()
+  {
+    return new SpatialInputNegotiator(indices_, type_, comm, intercomm);
+  }
+
+
+  /********************************************************************
+   *
+   * Cont Connectors
+   *
+   ********************************************************************/
+
+  void
+  ContConnector::initialize ()
+  {
+    Connector::initialize();
+    initialCommunication();
+  }
+
+
+  ClockState
+  ContConnector::remoteTickInterval (ClockState tickInterval)
+  {
+    ClockState::Serialized sRemoteTickInterval;
+    if (isLeader ())
+      {
+	// exchange tickInterval with peer leader
+	sRemoteTickInterval = tickInterval.serialize ();
+	intercomm.Sendrecv_replace (&sRemoteTickInterval, 2, MPI::UNSIGNED_LONG,
+				    0, TICKINTERVAL_MSG,
+				    0, TICKINTERVAL_MSG);
+      }
+    // broadcast to peers
+    comm.Bcast (&sRemoteTickInterval, 2, MPI::UNSIGNED_LONG, 0);
+    return sRemoteTickInterval.deserialize ();
+  }
+
+
+  ContOutputConnector::ContOutputConnector (ConnectorInfo connInfo,
+					    IndexMap* indices,
+					    Index::Type type,
+					    MPI::Intracomm comm,
+					    Sampler& sampler,
+					    MPI::Datatype data_type)
+    : Connector (connInfo, indices, type, comm),
+      ContConnector (sampler, data_type),
+      connector(NULL)
+  {
+  }
+
+  ContOutputConnector::ContOutputConnector (   Sampler& sampler,  MPI::Datatype type)
+    :  ContConnector (sampler, type),
+       connector(NULL)
+  {
+  }
+
+
+  ContOutputConnector::~ContOutputConnector()
+  {
+    if (connector != NULL)
+      delete connector;
+  }
+
+
+  Subconnector*
+  ContOutputConnector::makeSubconnector (int remoteRank)
+  {
+    return new ContOutputSubconnector (//synchronizer (),
+				       intercomm,
+				       remoteLeader (),
+				       remoteRank,
+				       receiverPortCode (),
+				       data_type_);
+  }
+
+
+  void
+  ContOutputConnector::specialize (Clock& localTime)
+  {
+    ClockState tickInterval = localTime.tickInterval ();
+    ClockState rTickInterval = remoteTickInterval (tickInterval);
+    localTime_ = &localTime;
+    remoteTime_.configure (localTime_->timebase (), rTickInterval);
+    if (tickInterval < rTickInterval)
+      connector = new InterpolatingContOutputConnector (this);
+    else
+      connector = new PlainContOutputConnector (this);
+  }
+
+  
+  void
+  ContOutputConnector::addRoutingInterval (IndexInterval i,
+					   Subconnector* subconn)
+  {
+    OutputSubconnector*osubconn= dynamic_cast<OutputSubconnector*>(subconn);
+    distributor_.addRoutingInterval (i, osubconn->outputBuffer());
+  }
+
+
+  void ContOutputConnector::initialCommunication()
+  {
+    for (std::vector<Subconnector*>::iterator s = rsubconn.begin (); s != rsubconn.end (); ++s)
+      (*s)->initialCommunication (0.0);
+  }
+  
+
+  void
+  PlainContOutputConnector::initialize ()
+  {
+    distributor_.configure (sampler_.dataMap ());
+    distributor_.initialize ();
+    // synch.initialize ();
+
+    // put one element in send buffers
+    distributor_.distribute ();
+  }
+
+
+  void
+  PlainContOutputConnector::preCommunication ()
+  {
+    if (sample ())
+      {
+	// copy application data to send buffers
+	distributor_.distribute ();
+
+      }
+  }
+
+
+  // Start sampling (and fill the output buffers) at a time dependent
+  // on latency and receiver's tick interval.  A negative latency can
+  // delay start of sampling beyond time 0.  The tickInterval together
+  // with the strict comparison has the purpose of supplying an
+  // interpolating receiver side with samples.
+  bool
+  PlainContOutputConnector::sample  ()
+  {
+    return (localTime_->integerTime () + latency + remoteTime_.tickInterval ()
+	    > 0);
+  }
+
+
+  void
+  InterpolatingContOutputConnector::initialize ()
+  {
+    // Set the remoteTime which is used to control sampling and
+    // interpolation.
+    //
+    // For positive latencies, the integer part (in terms of receiver
+    // ticks) of the latency is handled by filling up the receiver
+    // buffers using InputSynchronizer::initialBufferedTicks ().
+    // remoteTime then holds the fractional part.
+    if (latency > 0)
+      {
+	ClockState startTime = - latency % remoteTime_.tickInterval ();
+	if (latency >= localTime_->tickInterval ())
+	  startTime = startTime + remoteTime_.tickInterval ();
+	remoteTime_.set (startTime);
+      }
+    else
+      remoteTime_.set (- latency);
+    distributor_.configure (sampler_.interpolationDataMap ());
+    distributor_.initialize ();
+    // synch.initialize ();
+
+    // put one element in send buffers
+    sampler_.sample ();
+    sampler_.interpolate (1.0);
+    distributor_.distribute ();
+  }
+
+
+  // After the last sample at 1 localTime will be between remoteTime
+  // and remoteTime + localTime->tickInterval.  We trigger on this
+  // situation and forward remoteTime.
+  bool
+  InterpolatingContOutputConnector::sample()
+  {
+    ClockState sampleWindowLow
+      = remoteTime_.integerTime () - localTime_->tickInterval ();
+    ClockState sampleWindowHigh
+      = remoteTime_.integerTime () + localTime_->tickInterval ();
+    return (sampleWindowLow <= localTime_->integerTime ()
+	    && localTime_->integerTime () < sampleWindowHigh);
+  }
+
+
+  bool
+  InterpolatingContOutputConnector::interpolate()
+  {
+    ClockState sampleWindowHigh
+      = remoteTime_.integerTime () + localTime_->tickInterval ();
+    return (remoteTime_.integerTime () <= localTime_->integerTime ()
+	    && localTime_->integerTime () < sampleWindowHigh);
+  }
+
+
+  double
+  InterpolatingContOutputConnector::interpolationCoefficient()
+  {
+    ClockState prevSampleTime
+      = localTime_->integerTime () - localTime_->tickInterval ();
+    double c = ((double) (remoteTime_.integerTime () - prevSampleTime)
+		/ (double) localTime_->tickInterval ());
+
+    MUSIC_LOGR ("interpolationCoefficient = " << c);
+    // NOTE: preliminary implementation which just provides
+    // the functionality specified in the API
+    if (interp)
+      return c;
+    else
+      return round (c);
+  }
+
+
+  void
+  InterpolatingContOutputConnector::preCommunication ()
+  {
+    if (sample ()){
+      // sampling before and after time of receiver tick
+      sampler_.sampleOnce ();
+    }
+    if (interpolate ())
+      {
+	sampler_.interpolate (interpolationCoefficient ());
+	remoteTime_.tick();
+	distributor_.distribute ();
+      }
+  }
+
+
+  ContInputConnector::ContInputConnector (ConnectorInfo connInfo,
+		  	  	  	  IndexMap* indices,
+		  	  	  	  Index::Type type,
+					  MPI::Intracomm comm,
+					  Sampler& sampler,
+					  MPI::Datatype data_type,
+					  double delay)
+    : Connector (connInfo, indices, type, comm),
+      ContConnector (sampler, data_type),
+      delay_ (delay),
+      connector(NULL)
+  {
+  }
+
+
+  ContInputConnector::ContInputConnector ( Sampler& sampler, MPI::Datatype type,  double delay)
+    : ContConnector (sampler, type),
+      delay_ (delay),
+      connector(NULL)
+  {
+  }
+
+
+  ContInputConnector::~ContInputConnector()
+  {
+    if (connector != NULL)
+      delete connector;
+  }
+
+
+  Subconnector*
+  ContInputConnector::makeSubconnector (int remoteRank)
+  {
+    int receiverRank = intercomm.Get_rank ();
+    return new ContInputSubconnector (//synchronizer (),
+				      intercomm,
+				      remoteLeader (),
+				      remoteRank,
+				      receiverRank,
+				      receiverPortCode (),
+				      data_type_);
+  }
+
+
+  bool
+  ContInputConnector::divisibleDelay (Clock& localTime)
+  {
+    ClockState delay (delay_, localTime.timebase ());
+    return (delay % localTime.tickInterval ()) == 0;
+  }
+  
+
+  void
+  ContInputConnector::specialize (Clock& localTime)
+  {
+    ClockState tickInterval = localTime.tickInterval ();
+    ClockState rTickInterval = remoteTickInterval (tickInterval);
+    localTime_ = &localTime;
+    remoteTime_.configure (localTime_->timebase (), rTickInterval);
+
+    if (tickInterval < rTickInterval
+	|| (tickInterval == rTickInterval
+	    && !divisibleDelay (localTime)))
+      connector = new InterpolatingContInputConnector(this);
+    else
+      connector = new PlainContInputConnector (this);
+  }
+
+
+  void
+  ContInputConnector::initialCommunication()
+  {
+    double initialBTicks = initialBufferedTicks();
+    for (std::vector<Subconnector*>::iterator s = rsubconn.begin (); s != rsubconn.end (); ++s)
+      (*s)->initialCommunication (initialBTicks);
+  }
+
+
+  // Return the number of copies of the data sampled by the sender
+  // Runtime constructor which should be stored in the receiver
+  // buffers at the first tick () (which occurs at the end of the
+  // Runtime constructor)
+  int
+  ContInputConnector::initialBufferedTicks ()
+  {
+    if (remoteTime_.tickInterval () < localTime_->tickInterval ())
+      {
+	// InterpolatingOutputConnector - PlainInputConnector
+
+	if (delay_ <= 0)
+	  return 0;
+	else
+	  {
+	    // Need to add a sample first when we pass the receiver
+	    // tick (=> - 1).  If we haven't passed, the interpolator
+	    // could simply use an interpolation coefficient of 0.0.
+	    // (But this will never happen since that case isn't
+	    // handled by an InterpolatingOutputConnector.)
+	    int ticks = (delay_ - 1) / localTime_->tickInterval ();
+
+	    // Need to add a sample if we go outside of the sender
+	    // interpolation window
+	    if (delay_ >= remoteTime_.tickInterval ())
+	      ticks += 1;
+
+	    return ticks;
+	  }
+      }
+    else
+      {
+	// PlainOutputConnector - InterpolatingInputConnector
+
+	if (delay_ <= 0)
+	  return 0;
+	else
+	  // Need to add a sample first when we pass the receiver
+	  // tick (=> - 1).  If we haven't passed, the interpolator
+	  // can simply use an interpolation coefficient of 0.0.
+	  return 1 + (delay_ - 1) / localTime_->tickInterval ();
+      }
+  }
+
+
+  void
+  ContInputConnector::addRoutingInterval (IndexInterval i,
+					  Subconnector* subconn)
+  {
+    InputSubconnector*isubconn= dynamic_cast<InputSubconnector*>(subconn);
+    collector_.addRoutingInterval (i, isubconn->inputBuffer());
+  }
+
+
+  void
+  PlainContInputConnector::initialize ()
+  {
+    // collector_.configure (sampler_.dataMap (), synch.allowedBuffered () + 1);
+    collector_.configure (sampler_.dataMap (),  CONT_BUFFER_MAX);
+    collector_.initialize ();
+  }
+  
+
+  void
+  PlainContInputConnector::postCommunication ()
+  {
+    // collect data from input buffers and write to application
+    collector_.collect ();
+  }
+
+
+  void
+  InterpolatingContInputConnector::initialize ()
+  {
+    if (latency > 0)
+      remoteTime_.set (latency % remoteTime_.tickInterval ()
+		       - 2 * remoteTime_.tickInterval ());
+    else
+      remoteTime_.set (latency % remoteTime_.tickInterval ()
+		       - remoteTime_.tickInterval ());
+    //  collector_.configure (sampler_.interpolationDataMap (),
+    //			  synch.allowedBuffered () + 1);
+
+    collector_.configure (sampler_.interpolationDataMap (), CONT_BUFFER_MAX);
+    collector_.initialize ();
+
+
+    // synch.initialize ();
+  }
+
+
+  bool
+  InterpolatingContInputConnector::sample ()
+  {
+    return localTime_->integerTime () > remoteTime_.integerTime ();
+  }
+
+
+  double
+  InterpolatingContInputConnector::interpolationCoefficient ()
+  {
+    ClockState prevSampleTime
+      = remoteTime_.integerTime () - remoteTime_.tickInterval ();
+    double c = ((double) (localTime_->integerTime () - prevSampleTime)
+		/ (double) remoteTime_.tickInterval ());
+
+    MUSIC_LOGR ("interpolationCoefficient = " << c);
+    // NOTE: preliminary implementation which just provides
+    // the functionality specified in the API
+    if (interp)
+      return c;
+    else
+      return round (c);
+  }
+
+
+  void
+  InterpolatingContInputConnector::postCommunication ()
+  {
+    if (first_)
+      {
+	collector_.collect (sampler_.insert ());
+	remoteTime_.tick();
+	first_ = false;
+      }
+    else if (sample ())
+      {
+	collector_.collect (sampler_.insert ());
+	remoteTime_.tick();
+      }
+    sampler_.interpolateToApplication (interpolationCoefficient ());
+  }
+
+
+  /********************************************************************
+   *
+   * Event Connectors
+   *
+   ********************************************************************/
+
+
+  Subconnector*
+  EventOutputConnector::makeSubconnector (int remoteRank)
+  {
+    //////
+/*                int world_size = MPI::COMM_WORLD.Get_size();
+                if (MPI::COMM_WORLD.Get_rank() < world_size/2)
+                  std::cout << remoteRank << std::flush << std::endl;*/
+    return new EventOutputSubconnector (//&synch,
+					intercomm,
+					remoteLeader (),
+					remoteRank,
+					receiverPortCode ());
+  }
+
+
+  void
+  EventOutputConnector::addRoutingInterval (IndexInterval i,
+					    Subconnector* subconn)
+  {
+    OutputSubconnector* osubconn= dynamic_cast<OutputSubconnector*>(subconn);
+    routingMap_-> insert (i, osubconn->outputBuffer());
+  }
+
+  Subconnector*
+  EventInputConnector::makeSubconnector (int remoteRank)
+  {
+    int receiverRank = intercomm.Get_rank ();
+    if (type_ == Index::GLOBAL){
+    	EventInputSubconnectorGlobal *subcc =
+    	 new EventInputSubconnectorGlobal (//&synch,
+					       intercomm,
+					       remoteLeader (),
+					       remoteRank,
+					       receiverRank,
+					       receiverPortCode (),
+					       handleEvent_);
+    	rRank2Subconnector[remoteRank] = subcc;
+    	flushes++;
+    	return subcc;
+    }
+    else
+      {
+#if MUSIC_ANYSOURCE
+error( "LOCAL Indices are not supported with MUSIC_ANYSOURCE");
+#endif
+
+      return new EventInputSubconnectorLocal (//&synch,
+					      intercomm,
+					      remoteLeader (),
+					      remoteRank,
+					      receiverRank,
+					      receiverPortCode (),
+					      handleEvent_);
+      }
+  }
+
+
+
+  void
+  EventInputConnector::addRoutingInterval(IndexInterval i, Subconnector* subconn)
+  {
+    //routingMap_-> insert (i, handleEvent_.global());
+  }
+#if MUSIC_ANYSOURCE
+ void
+ EventInputConnector::tick ()
+   {
+	  //SPIKE_BUFFER_MAX size
+	  //MPI::BYTE type
+	  //SPIKE_MSG tag
+	  int size = rsubconn.size();
+	  char data[SPIKE_BUFFER_MAX];
+	  MPI::Status status;
+	  while(size > 0 && flushes > 0){
+	  intercomm.Recv (data,
+	  				SPIKE_BUFFER_MAX,
+	  				MPI::BYTE,
+	  				MPI_ANY_SOURCE,
+	  				SPIKE_MSG,
+	  				status);
+
+	  int msize = status.Get_count(MPI::BYTE);
+	  if (rRank2Subconnector[status.Get_source()]->receive(data, msize))
+		  flushes--;
+	  if( msize < SPIKE_BUFFER_MAX)
+		 size--;
+	  }
+   }
+#endif //MUSIC_ANYSOURCE
+  /********************************************************************
+   *
+   * Message Connectors
+   *
+   ********************************************************************/
+  
+  MessageOutputConnector::MessageOutputConnector (ConnectorInfo connInfo,
+		  	  	  	  	  IndexMap* indices,
+		  	  	  	  	  Index::Type type,
+						  MPI::Intracomm comm,
+						  std::vector<FIBO*>& buffers)
+    : Connector (connInfo, indices, type, comm),
+      buffer (1),
+      bufferAdded (false),
+      buffers_ (buffers)
+  {
+  }
+
+
+
+  
+  Subconnector*
+  MessageOutputConnector::makeSubconnector (int remoteRank)
+  {
+    return new MessageOutputSubconnector (//&synch,
+					  intercomm,
+					  remoteLeader (),
+					  remoteRank,
+					  receiverPortCode (),
+					  &buffer);
+  }
+
+
+  void
+  MessageOutputConnector::addRoutingInterval (IndexInterval i,
+					      Subconnector* subconn)
+  {
+    if (!bufferAdded)
+      {
+	buffers_.push_back (&buffer);
+	bufferAdded = true;
+      }
+  }
+  
+  
+
+
+  
+  void
+  MessageOutputConnector::postCommunication ()
+  {
+    //   if (synch.communicate ())
+    buffer.clear ();
+  }
+
+  
+  MessageInputConnector::MessageInputConnector (ConnectorInfo connInfo,
+						IndexMap* indices,
+						Index::Type type,
+						MessageHandler* handleMessage,
+						MPI::Intracomm comm)
+    : Connector (connInfo, indices, type, comm),
+      handleMessage_ (handleMessage)
+  {
+  }
+
+
+
+  
+  Subconnector*
+  MessageInputConnector::makeSubconnector (int remoteRank)
+  {
+    int receiverRank = intercomm.Get_rank ();
+    return new MessageInputSubconnector (//&synch,
+					 intercomm,
+					 remoteLeader (),
+					 remoteRank,
+					 receiverRank,
+					 receiverPortCode (),
+					 handleMessage_);
+  }
+
+  /********************************************************************
+   *
+   * Collective Connector
+   *
+   ********************************************************************/
+
+  CollectiveConnector::CollectiveConnector (bool high)
+    : high_ (high), subconnector_ (NULL)
+  {
+    //idFlag_ = makeFlag ();
+  }
+
+
+  void
+  CollectiveConnector::createIntercomm ()
+  {
+    Connector::createIntercomm ();
+    intracomm_ = intercomm.Merge (high_);
+  }
+
+
+  void
+  CollectiveConnector::freeIntercomm ()
+  {
+    intracomm_.Free ();
+    Connector::freeIntercomm ();
+  }
+
+
+  ContCollectiveConnector::ContCollectiveConnector (MPI::Datatype type,
+						    bool high):
+    CollectiveConnector (high),
+    data_type (type)
+  {
+
+  }
+
+
+  Subconnector*
+  ContCollectiveConnector::makeSubconnector (void *param)
+  {
+    std::multimap< int, Interval> intrvs
+      = *static_cast< std::multimap< int, Interval>*> (param);
+    if (subconnector_ == NULL)
+      {
+	subconnector_ = new ContCollectiveSubconnector (intrvs,
+							width (),
+							intracomm_,
+							data_type);
+      }
+    return subconnector_;
+  }
+
+
+  EventCollectiveConnector::EventCollectiveConnector (bool high)
+    : CollectiveConnector (high), router_ (NULL)
+  {
+    idFlag_ = makeFlag (this);
+  }
+
+
+  Subconnector*
+  EventInputCollectiveConnector::makeSubconnector (void *param)
+  {
+    if (subconnector_ == NULL)
+      subconnector_ = new EventInputCollectiveSubconnector (router_);
+    return subconnector_;
+  }
+
+
+  EventInputCollectiveConnector::EventInputCollectiveConnector
+  (ConnectorInfo connInfo,
+   IndexMap* indices,
+   Index::Type type,
+   MPI::Intracomm comm,
+   EventHandlerPtr handleEvent)
+    : Connector (connInfo, indices, type, comm),
+      EventInputConnector (handleEvent),
+      EventCollectiveConnector (true)
+  {
+
+    int procMethod = connInfo.processingMethod ();
+    if (procMethod == ConnectorInfo::TREE)
+      if (handleEvent.getType () == Index::GLOBAL)
+	router_ = new TreeProcessingInputGlobalRouter ();
+      else
+	router_ = new TreeProcessingInputLocalRouter ();
+    else
+      if (handleEvent.getType () == Index::GLOBAL)
+	router_ = new TableProcessingInputGlobalRouter ();
+      else
+	router_ = new TableProcessingInputLocalRouter ();
+  }
+
+
+  EventInputCollectiveConnector::~EventInputCollectiveConnector()
+  {
+    delete router_;
+  }
+
+
+  void
+  EventInputCollectiveConnector::spatialNegotiation (SpatialNegotiator* spatialNegotiator_)
+  {
+    routingMap_input = new InputRoutingMap ();
+    Subconnector* subconn
+      = EventInputCollectiveConnector::makeSubconnector (NULL);
+    rsubconn.push_back (subconn);
+    for (NegotiationIterator i = spatialNegotiator_->negotiateSimple (); !i.end (); ++i)
+      addRoutingInterval (i->interval (), subconn);
+    routingMap_input->fillRouter (router_);
+    delete routingMap_input;
+    router_->buildTable ();
+  }
+
+
+  void
+  EventInputCollectiveConnector::addRoutingInterval (IndexInterval i,
+						     Subconnector* subconn)
+  {
+    routingMap_input->insert (i, &handleEvent_);
+  }
+
+
+  EventOutputCollectiveConnector::EventOutputCollectiveConnector
+  (ConnectorInfo connInfo,
+   IndexMap* indices,
+   Index::Type type,
+   MPI::Intracomm comm,
+   DirectRouter* router)
+    : Connector (connInfo, indices, type, comm),
+      EventOutputConnector (NULL),
+      EventCollectiveConnector (false),
+      directRouter_ (router)
+  {
+  }
+
+
+  EventOutputCollectiveConnector::~EventOutputCollectiveConnector()
+  {
+  }
+
+
+  Subconnector*
+  EventOutputCollectiveConnector::makeSubconnector (void *param)
+  {
+    //  EventRouter * router_ = static_cast<EventRouter*>(param);
+    if(subconnector_ == NULL){
+      subconnector_ = new EventOutputCollectiveSubconnector ();
+    }
+    return subconnector_;
+  }
+
+  void
+  EventOutputCollectiveConnector::spatialNegotiation (SpatialNegotiator* spatialNegotiator_)
+  {
+    EventOutputCollectiveSubconnector* subconn
+      = dynamic_cast<EventOutputCollectiveSubconnector*>
+      (EventOutputCollectiveConnector::makeSubconnector (NULL));
+    rsubconn.push_back (subconn);
+    subconn->setRouter (directRouter_);
+    //spatialNegotiator_->negotiateSimple ();
+  }
+
+
+  ContInputCollectiveConnector::ContInputCollectiveConnector
+  (ConnectorInfo connInfo,
+   IndexMap* indices,
+   Index::Type type,
+   MPI::Intracomm comm,
+   Sampler& sampler,
+   MPI::Datatype data_type,
+   double delay)
+    : Connector(connInfo, indices,type, comm),
+      ContInputConnector(sampler, data_type, delay),
+      ContCollectiveConnector(data_type, true)
+  {
+
+  }
+
+
+  void
+  ContInputCollectiveConnector::spatialNegotiation (SpatialNegotiator* spatialNegotiator_)
+  {
+    std::multimap< int, Interval> receiver_intrvs;
+    std::vector<IndexInterval> intrvs;
+    std::map<int,int> remoteToCollectiveRankMap;
+    receiveRemoteCommRankID(remoteToCollectiveRankMap);
+
+    for (NegotiationIterator i  = spatialNegotiator_->negotiate (info.nProcesses (), this);  !i.end (); ++i)
+      {
+	int begin = (i->displ())*data_type_.Get_size();
+	// length field is stored overlapping the end field
+	int end = (i->end() - i->begin()) * data_type_.Get_size();
+	receiver_intrvs.insert (std::make_pair ( remoteToCollectiveRankMap[i->rank ()], Interval(begin, end)));
+	intrvs.push_back(i->interval());
+      }
+
+    Subconnector *subconn = ContCollectiveConnector::makeSubconnector(&receiver_intrvs);
+    rsubconn.push_back (subconn);
+    for (std::vector<IndexInterval>::iterator  it=intrvs.begin() ; it < intrvs.end(); it++ )
+      addRoutingInterval ((*it), subconn);
+  }
+
+
+  void
+  ContInputCollectiveConnector::receiveRemoteCommRankID(std::map<int,int> &remoteToCollectiveRankMap)
+  {
+    int nProcesses, intra_rank;
+    nProcesses = intercomm.Get_remote_size();
+
+    for (int i =0; i < nProcesses; ++i)
+      {
+	intercomm.Recv (&intra_rank,
+			1,
+			MPI::INT,
+			i,
+			SPATIAL_NEGOTIATION_MSG);
+	remoteToCollectiveRankMap.insert(std::make_pair(i,intra_rank));
+	MUSIC_LOG0( "Remote Communication Rank:" << i << "is mapped to Collective Communication Rank:" << intra_rank );
+      }
+
+  }
+
+
+  ContOutputCollectiveConnector::ContOutputCollectiveConnector(ConnectorInfo connInfo,
+							       IndexMap* indices,
+							       Index::Type type,
+							       MPI::Intracomm comm,
+							       Sampler& sampler,
+							       MPI::Datatype data_type):
+    Connector(connInfo, indices,type, comm),
+    ContOutputConnector( sampler, data_type),
+    ContCollectiveConnector(data_type, false)
+  {
+
+  }
+
+
+  void
+  ContOutputCollectiveConnector::spatialNegotiation ( SpatialNegotiator* spatialNegotiator_)
+  {
+    sendLocalCommRankID();
+    std::map<Interval, int>  empty_intrvs;
+    Subconnector *subconn = ContCollectiveConnector::makeSubconnector(&empty_intrvs);
+    rsubconn.push_back (subconn);
+    spatialNegotiator_->negotiate (info.nProcesses (), this);
+    for (NegotiationIterator i = spatialNegotiator_->negotiateSimple (); !i.end (); ++i)
+      addRoutingInterval (i->interval(), subconn);
+  }
+
+
+  void
+  ContOutputCollectiveConnector::sendLocalCommRankID()
+  {
+    int nProcesses, intra_rank;
+    nProcesses = intercomm.Get_remote_size();
+    intra_rank = intracomm_.Get_rank();
+    std::map<int,int> rCommToCollCommRankMap;
+    for (int i =0; i < nProcesses; ++i){
+      intercomm.Ssend(&intra_rank,
+		      1,
+		      MPI::INT,
+		      i,
+		      SPATIAL_NEGOTIATION_MSG);
+    }
+  }
+}
+#endif
diff --git a/src/distributor.cc b/src/distributor.cc
new file mode 100644
index 0000000..cffe102
--- /dev/null
+++ b/src/distributor.cc
@@ -0,0 +1,146 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/distributor.hh"
+
+#include "music/debug.hh"
+
+#if MUSIC_USE_MPI
+
+// distributor.hh needs to be included first since it causes inclusion
+// of mpi.h (in data_map.hh).  mpi.h must be included before other
+// header files on BG/L
+
+
+#include <algorithm>
+#include <cstring>
+
+#include "music/event.hh"
+
+namespace MUSIC {
+
+  Distributor::Interval::Interval (IndexInterval& interval)
+  {
+    setBegin (interval.begin ());
+    setLength (interval.end () - interval.begin ());
+  }
+  
+
+  void
+  Distributor::configure (DataMap* dmap)
+  {
+    dataMap = dmap;
+  }
+
+  
+  IntervalTree<int, MUSIC::Interval, int>*
+  Distributor::buildTree ()
+  {
+    IntervalTree<int, MUSIC::Interval, int>* tree
+      = new IntervalTree<int, MUSIC::Interval, int> ();
+    
+    IndexMap* indices = dataMap->indexMap ();
+    for (IndexMap::iterator i = indices->begin ();
+	 i != indices->end ();
+	 ++i)
+      {
+	MUSIC_LOGR ("adding (" << i->begin () << ", " << i->end ()
+		    << ", " << i->local () << ") to tree");
+	tree->add (*i, i->local ());
+      }
+
+    tree->build ();
+    
+    return tree;
+  }
+  
+
+  void
+  Distributor::addRoutingInterval (IndexInterval interval, FIBO* buffer)
+  {
+    BufferMap::iterator b = buffers.find (buffer);
+    if (b == buffers.end ())
+      {
+	buffers.insert (std::make_pair (buffer, Intervals ()));
+	b = buffers.find (buffer);
+      }
+    Intervals& intervals = b->second;
+    intervals.push_back (Interval (interval));
+  }
+
+
+  void
+  Distributor::IntervalCalculator::operator() (int& offset)
+  {
+    interval_.setBegin (elementSize_
+			* (interval_.begin () - offset));
+    interval_.setLength (elementSize_ * interval_.length ());
+  }
+
+
+  void
+  Distributor::initialize ()
+  {
+    IntervalTree<int, MUSIC::Interval, int>* tree = buildTree ();
+    
+    for (BufferMap::iterator b = buffers.begin (); b != buffers.end (); ++b)
+      {
+	FIBO* buffer = b->first;
+	Intervals& intervals = b->second;
+	sort (intervals.begin (), intervals.end ());
+	int elementSize = dataMap->type ().Get_size ();
+	int size = 0;
+	for (Intervals::iterator i = intervals.begin ();
+	     i != intervals.end ();
+	     ++i)
+	  {
+	    IntervalCalculator calculator (*i, elementSize);
+	    tree->search (i->begin (), &calculator);
+	    size += i->length ();
+	  }
+	buffer->configure (size);
+      }
+
+    delete tree;
+  }
+
+
+  void
+  Distributor::distribute ()
+  {
+    for (BufferMap::iterator b = buffers.begin (); b != buffers.end (); ++b)
+      {
+	FIBO* buffer = b->first;
+	Intervals& intervals = b->second;
+	ContDataT* src = static_cast<ContDataT*> (dataMap->base ());
+	ContDataT* dest = static_cast<ContDataT*> (buffer->insert ());
+	for (Intervals::iterator i = intervals.begin ();
+	     i != intervals.end ();
+	     ++i)
+	  {
+	    MUSIC_LOGR ("src = " << static_cast<void*> (src)
+		       << ", begin = " << i->begin ()
+		       << ", length = " << i->length ());
+	    memcpy (dest, src + i->begin (), i->length ());
+	    dest += i->length ();
+	  }
+      }
+  }
+  
+}
+#endif
diff --git a/src/error.cc b/src/error.cc
new file mode 100644
index 0000000..1f617ef
--- /dev/null
+++ b/src/error.cc
@@ -0,0 +1,127 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/music-config.hh"
+
+#if MUSIC_USE_MPI
+#include <mpi.h>
+#endif
+
+#include "music/error.hh"
+
+#include <iostream>
+#include <stdlib.h>
+
+namespace MUSIC {
+
+  void
+  error ()
+  {
+#if MUSIC_USE_MPI
+    MPI::COMM_WORLD.Abort (1);
+#else
+    abort();
+#endif
+  }
+
+
+  void
+  hang ()
+  {
+    while (true)
+      ;
+  }
+  
+  
+  void
+  error (std::string msg)
+  {
+    std::cerr << "Error in MUSIC library: " << msg << std::endl;
+    error ();
+  }
+
+
+  void
+  error (std::ostringstream& ostr)
+  {
+    error (ostr.str ());
+  }
+
+
+  static int
+  getRank ()
+  {
+#if MUSIC_USE_MPI
+    if (MPI::Is_initialized ())
+      return MPI::COMM_WORLD.Get_rank ();
+#endif
+      return -1;
+  }
+
+  
+  void
+  error0 (std::string msg)
+  {
+    if (getRank () <= 0)
+      error (msg);
+    else
+      // Give process #0 a chance to report the error
+      hang ();
+  }
+
+
+  void
+  errorRank (std::string msg)
+  {
+    std::ostringstream text;
+    int rank = getRank ();
+    if (rank >= 0)
+      text << "rank #" << rank << ": ";
+    text << msg;
+    error (text.str ());
+  }
+  
+  
+  void
+  checkOnce (bool& flag, std::string msg)
+  {
+    if (flag)
+      errorRank (msg);
+    flag = true;
+  }
+
+
+  void
+  checkInstantiatedOnce (bool& isInstantiated, std::string className)
+  {
+    std::ostringstream msg;
+    msg << className << " constructor was called a second time.\n"
+      "Only one " << className << " object can exist at any instance of time.";
+    checkOnce (isInstantiated, msg.str ());
+  }
+
+  
+  void
+  checkCalledOnce (bool& isCalled, std::string funcName, std::string suffix)
+  {
+    std::ostringstream msg;
+    msg << funcName << " called twice" << suffix;
+    checkOnce (isCalled, msg.str ());
+  }
+  
+}
diff --git a/src/event_data.cc b/src/event_data.cc
new file mode 100644
index 0000000..7462cde
--- /dev/null
+++ b/src/event_data.cc
@@ -0,0 +1,31 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008 CSC, KTH
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "music/index_map.hh"
+namespace MUSIC {
+  
+  event_data::event_data (index_map* map)
+    : data_map (map)
+  {
+  }
+
+  event_data::event_data (int baseindex, int size)
+    : data_map (new linear_index (baseindex, size))
+  {
+  }
+
+}
diff --git a/src/event_router.cc b/src/event_router.cc
new file mode 100644
index 0000000..6bfbf49
--- /dev/null
+++ b/src/event_router.cc
@@ -0,0 +1,75 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/event.hh"
+#include "music/event_router.hh"
+
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+
+namespace MUSIC {
+
+  OutputRoutingData::OutputRoutingData (const IndexInterval &i, FIBO* b) : EventRoutingData(i), buffer_ (b)
+  {
+  }
+
+  void
+  OutputRoutingData::process (double t, int id)
+  {
+    Event* e = static_cast<Event*> (buffer_->insert ());
+    e->t = t;
+    e->id = id;
+  }
+
+  void
+  DirectRouter::processExtra (double t, int id)
+  {
+    unsigned int pos = extra_.size ();
+    extra_.resize (pos + sizeof (Event));
+    Event* e = static_cast<Event*> (static_cast<void*> (&extra_[pos]));
+    e->t = t;
+    e->id = id;
+  }
+
+  void
+  DirectRouter::setOutputBuffer (void* buffer, unsigned int size)
+  {
+    if (size == size_)
+      {
+	// Buffer relocated
+	buffer_ = static_cast<char*> (buffer);
+	return;
+      }
+#if 0
+    if (size - size_ != extra_.size ())
+      std::cout << "Rank " << MPI::COMM_WORLD.Get_rank ()
+		<< ": DirectRouter: Had " << extra_.size ()
+		<< " extra spike space, size changed from "
+		<< size_ << " to " << size << " = " << size - size_
+		<< std::endl;
+#endif
+    assert (size - size_ == extra_.size ());
+    buffer_ = static_cast<char*> (buffer);
+    memcpy (buffer_ + size_, &extra_[0], extra_.size ());
+    extra_.clear ();
+    std::vector<char> (extra_).swap (extra_); // trim
+    size_ = size;
+  }
+
+}
diff --git a/src/event_routing_map.cc b/src/event_routing_map.cc
new file mode 100644
index 0000000..2efafda
--- /dev/null
+++ b/src/event_routing_map.cc
@@ -0,0 +1,124 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//#define MUSIC_DEBUG
+//#include "music/music-config.hh"
+
+#include "music/event_router.hh"
+#include "music/event_routing_map.hh"
+
+namespace MUSIC {
+
+  void
+  OutputRoutingMap::insertRoutingInterval (EventRouter *router, IndexInterval i, FIBO *b)
+  {
+    OutputRoutingData data_ (i, b);
+    router->insertRoutingData (i, data_);
+  }
+
+  OutputRoutingMap::~OutputRoutingMap()
+  {
+    delete intervals;
+  }
+
+  void
+  OutputRoutingMap::insert (IndexInterval i, FIBO* data)
+  {
+    EventRoutingMap<FIBO*>::insert (i, data);
+    intervals->push_back (dataMap[data].back ());
+  }
+
+  void
+  OutputRoutingMap::fillRouter (EventRouter *router)
+  {
+    std::vector<IndexInterval> new_intervals = rebuildIntervals (*intervals);
+    //std::vector<IndexInterval*> new_intervals = *intervals;
+    std::map<FIBO*, std::vector<IndexInterval *> >::iterator pos;
+    for (pos = dataMap.begin (); pos != dataMap.end (); ++pos)
+      {
+	sort (pos->second.begin (), pos->second.end (), comp_obj);
+
+	std::vector<IndexInterval*>::iterator i = pos->second.begin ();
+
+	if (router->needFewPoints ())
+	  {
+	    // insert intervals without trying to close gaps
+	    while (i != pos->second.end ())
+	      insertRoutingInterval (router, **i++, pos->first);
+	    continue;
+	  }
+	
+	std::vector<IndexInterval>::iterator mapped = new_intervals.begin ();
+	while (i != pos->second.end ())
+	  {
+	    IndexInterval current = **i++;
+	    while (i != pos->second.end ()
+		   && (*i)->local () == current.local ())
+	      {
+		// Define the gap between current and next interval
+		int gapBegin = current.end ();
+		int gapEnd = (*i)->begin ();
+
+		// Skip mapped intervals which end before gap
+		while (mapped != new_intervals.end ()
+		       && (*mapped).end () <= gapBegin){
+
+		  ++mapped;
+		}
+		// Check that gap does not overlap with any mapped interval
+		if (mapped != new_intervals.end () && (*mapped).begin () < gapEnd)
+		  break;
+		// Join intervals by closing over gap
+		current.setEnd ((*i)->end ());
+		++i;
+	      }
+	    insertRoutingInterval (router, current, pos->first);
+	  }
+      }
+  }
+
+
+  void
+  InputRoutingMap::insertRoutingInterval (EventRouter *router,
+					  IndexInterval i,
+					  EventHandlerPtr *h)
+  {
+    if (h->getType () == Index::GLOBAL)
+      {
+	InputRoutingData<EventHandlerGlobalIndex> data_ (i, h);
+	router->insertRoutingData (i, data_);
+      }
+    else
+      {
+	InputRoutingData<EventHandlerLocalIndex> data_ (i, h);
+	router->insertRoutingData (i, data_);
+      }
+  }
+
+  void InputRoutingMap::fillRouter (EventRouter *router)
+  {
+    std::map<EventHandlerPtr*, std::vector<IndexInterval *> >::iterator pos;
+    for (pos = dataMap.begin (); pos != dataMap.end (); ++pos)
+      {
+	std::vector<IndexInterval > new_intervals = rebuildIntervals (((*pos).second));
+	std::vector<IndexInterval >::iterator i = new_intervals.begin ();
+	while (i != new_intervals.end ())
+	  insertRoutingInterval (router, *i++, (*pos).first);
+      }
+  }
+}
diff --git a/src/index_map.cc b/src/index_map.cc
new file mode 100644
index 0000000..4cef814
--- /dev/null
+++ b/src/index_map.cc
@@ -0,0 +1,67 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <limits>
+
+#include "music/index_map.hh"
+
+namespace MUSIC {
+
+  int Index::WILDCARD_MAX = std::numeric_limits<int>::max ();
+
+  bool operator< (const IndexInterval& a, const IndexInterval& b)
+  {
+    return (a.begin () < b.begin ()
+	    || (a.begin () == b.begin () && a.end () < b.end ()));
+  }
+  
+  const IndexInterval
+  IndexMap::iterator::operator* ()
+  {
+    return **implementation_;
+  }
+  
+
+  const IndexInterval*
+  IndexMap::iterator::operator-> ()
+  {
+    return implementation_->dereference ();
+  }
+  
+
+  bool
+  IndexMap::iterator::operator== (const iterator& i) const
+  {
+    return implementation_->isEqual (i.implementation ());
+  }
+  
+
+  bool
+  IndexMap::iterator::operator!= (const iterator& i) const
+  {
+    return !implementation_->isEqual (i.implementation ());
+  }
+  
+
+  IndexMap::iterator&
+  IndexMap::iterator::operator++ ()
+  {
+    ++*implementation_;
+    return *this;
+  }
+
+}
diff --git a/src/index_map_factory.cc b/src/index_map_factory.cc
new file mode 100644
index 0000000..24ee79a
--- /dev/null
+++ b/src/index_map_factory.cc
@@ -0,0 +1,68 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/index_map_factory.hh"
+#include <algorithm>
+namespace MUSIC {
+  
+  IndexMapFactory::IndexMapFactory ()
+  {
+  }
+  
+
+  IndexMapFactory::IndexMapFactory (std::vector<IndexInterval>& indices)
+    : indices_ (indices)
+  {
+  }
+
+
+  void
+  IndexMapFactory::add (int begin, int end, int local)
+  {
+    indices_.push_back (IndexInterval (begin, end, begin - local));
+  }
+  
+
+  void
+  IndexMapFactory::build ()
+  {
+    sort (indices_.begin (), indices_.end ());
+  }
+  
+
+  IndexMap::iterator
+  IndexMapFactory::begin ()
+  {
+    return IndexMap::iterator (new iterator (&indices_.front ()));
+  }
+
+  
+  const IndexMap::iterator
+  IndexMapFactory::end () const
+  {
+    return IndexMap::iterator (new iterator (&indices_.back () + 1));
+  }
+
+
+  IndexMap*
+  IndexMapFactory::copy ()
+  {
+    return new IndexMapFactory (indices_);
+  }
+
+}
diff --git a/src/interval.cc b/src/interval.cc
new file mode 100644
index 0000000..3f05ef8
--- /dev/null
+++ b/src/interval.cc
@@ -0,0 +1,31 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/interval.hh"
+
+namespace MUSIC {
+
+  // support printed representation
+  std::ostream&
+  operator<< (std::ostream& os, const Interval& ival)
+  {
+    os << "[" << ival.begin () << ", " << ival.end () << ")";
+    return os;
+  }
+
+}
diff --git a/src/ioutils.cc b/src/ioutils.cc
new file mode 100644
index 0000000..e57baf2
--- /dev/null
+++ b/src/ioutils.cc
@@ -0,0 +1,85 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <cstdio>
+
+#include "music/ioutils.hh"
+
+namespace MUSIC {
+
+  namespace IOUtils {
+    
+    void
+    write (std::ostringstream& out, std::string s)
+    {
+      std::istringstream value (s);
+      while (true)
+	{
+	  int c;
+	  switch (c = value.get ())
+	    {
+	    case '\\':
+	    case ':':
+	      out << '\\';
+	    default:
+	      out << (char) c;
+	      continue;
+	    case EOF:
+	      break;
+	    }
+	  break;
+	}
+    }
+
+  
+    std::string
+    read (std::istringstream& in, int delim)
+    {
+      std::ostringstream value;
+      while (true)
+	{
+	  int c = in.peek ();
+	  switch (c)
+	    {
+	    case '\\':
+	      in.get ();
+	      value << (char) in.get ();
+	      continue;
+	    default:
+	      if (c == delim)
+		break;
+	      value << (char) in.get ();
+	      continue;
+	    case EOF:
+	      break;
+	    }
+	  break;
+	}
+      return value.str ();
+    }
+
+  
+    std::string
+    read (std::istringstream& in)
+    {
+      return read (in, ':');
+    }
+
+  }
+  
+}
diff --git a/src/linear_index.cc b/src/linear_index.cc
new file mode 100644
index 0000000..ff230a7
--- /dev/null
+++ b/src/linear_index.cc
@@ -0,0 +1,84 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/linear_index.hh"
+
+namespace MUSIC {
+  
+  LinearIndex::iterator::iterator (LinearIndex* li)
+    : indices_ (li)
+  {
+  }
+
+
+  const IndexInterval
+  LinearIndex::iterator::operator* ()
+  {
+    return indices_->interval_;
+  }
+
+
+  const IndexInterval*
+  LinearIndex::iterator::dereference ()
+  {
+    return &indices_->interval_;
+  }
+
+
+  void
+  LinearIndex::iterator::operator++ ()
+  {
+    indices_ = 0;
+  }
+
+
+  bool
+  LinearIndex::iterator::isEqual (IteratorImplementation* i) const
+  {
+    return indices_ == static_cast<iterator*> (i)->indices_;
+  }
+  
+  
+  LinearIndex::LinearIndex (GlobalIndex baseindex, int size)
+    : interval_ (baseindex, baseindex + size, static_cast<int> (baseindex))
+  {
+
+  }
+
+
+  IndexMap::iterator
+  LinearIndex::begin ()
+  {
+    return IndexMap::iterator (new iterator (this));
+  }
+
+  
+  const IndexMap::iterator
+  LinearIndex::end () const
+  {
+    return IndexMap::iterator (new iterator (0));
+  }
+
+
+  IndexMap*
+  LinearIndex::copy ()
+  {
+    return new LinearIndex (*this);
+  }
+  
+}
diff --git a/src/memory.cc b/src/memory.cc
new file mode 100644
index 0000000..d516da2
--- /dev/null
+++ b/src/memory.cc
@@ -0,0 +1,43 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <iostream>
+
+extern "C" {
+#include <malloc.h>
+}
+
+#include "music/memory.hh"
+
+#include "../config.h"
+
+namespace MUSIC {
+
+  void
+  reportMem ()
+  {
+#ifdef HAVE_MALLINFO
+    struct mallinfo minfo = mallinfo ();
+    std::cout << "Allocated with sbrk (arena): " << minfo.arena << std::endl;
+    std::cout << "Allocated with mmap (hblkhd): " << minfo.hblkhd << std::endl;
+    std::cout << "Chunks handed out by malloc (uordblks): " << minfo.uordblks << std::endl;
+    std::cout << "Free memory in pool (fordblks): " << minfo.fordblks << std::endl;
+#endif
+  }
+
+}
diff --git a/src/multibuffer.cc b/src/multibuffer.cc
new file mode 100644
index 0000000..334658e
--- /dev/null
+++ b/src/multibuffer.cc
@@ -0,0 +1,963 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/multibuffer.hh"
+
+#include "music/debug.hh"
+
+#include <sstream>
+
+#include <cstring>
+
+extern "C" {
+#include <assert.h>
+}
+
+#if MUSIC_USE_MPI
+
+namespace MUSIC {
+
+  /********************************************************************
+   *
+   * MultiBuffer
+   *
+   ********************************************************************/
+
+  MultiBuffer::MultiBuffer (MPI::Intracomm comm,
+			    int localLeader,
+			    std::vector<Connector*>& connectors)
+    : localLeader_ (localLeader)
+  {
+    //bool hang = true;
+    //while (hang) ;
+    MPI::Group worldGroup = MPI::COMM_WORLD.Get_group ();
+    MPI::Group localGroup = comm.Get_group ();
+    int localSize = localGroup.Get_size ();
+
+    // maps leaders to vectors mapping local ranks to COMM_WORLD ranks
+    RankMap* rankMap = new RankMap ();
+    setupRankMap (comm.Get_rank (), rankMap);
+#if 0
+    std::ostringstream ostr;
+    ostr << "Rank " << MPI::COMM_WORLD.Get_rank () << ": rankMap ";
+    for (RankMap::iterator i = rankMap->begin ();
+	 i != rankMap->end ();
+	 ++i)
+      {
+	ostr << i->first << ": ";
+	std::vector<int>& ranks = i->second;
+	for (std::vector<int>::iterator j = ranks.begin ();
+	     j != ranks.end ();
+	     ++j)
+	  ostr << *j << " ";
+	ostr << " ";
+      }
+    std::cout << ostr.str () << std::endl;
+#endif
+
+    for (std::vector<Connector*>::iterator c = connectors.begin ();
+	 c != connectors.end ();
+	 ++c)
+      {
+	// supports multicommunication?
+	if (!(*c)->idFlag ())
+	  continue;
+	
+	CollectiveConnector* connector
+	  = dynamic_cast<CollectiveConnector*> (*c);
+
+	// We create InputSubconnectorInfo:s also for output connectors.
+	// In this case s will be NULL.
+	InputSubconnector* s
+	  = dynamic_cast<InputSubconnector*> (connector->subconnector ());
+	std::pair<InputConnectorMap::iterator, bool> res
+	  = inputConnectorMap_.insert
+	  (InputConnectorMap::value_type (connector,
+					  InputSubconnectorInfo (s)));
+	InputSubconnectorInfo& isi = res.first->second;
+
+	// decide group leader and size
+	int outputLeader;
+	int outputSize;
+	int inputLeader;
+	int inputSize;
+	if (connector->isInput ())
+	  {
+	    outputLeader = connector->remoteLeader ();
+	    outputSize = connector->remoteNProcs ();
+	    inputLeader = localLeader;
+	    inputSize = localSize;
+	  }
+	else
+	  {
+	    outputLeader = localLeader;
+	    outputSize = localSize;
+	    inputLeader = connector->remoteLeader ();
+	    inputSize = connector->remoteNProcs ();
+	  }
+	
+	// setup BufferInfo array
+	isi.setSize (outputSize);
+
+	if (!connector->isInput ())
+	  {
+	    // create OutputSubconnectorInfo
+	    OutputSubconnector* s
+	      = dynamic_cast<OutputSubconnector*> (connector->subconnector ());
+	    BufferInfo* bi = &*(isi.begin () + comm.Get_rank ());
+	    outputConnectorMap_.insert
+	      (OutputConnectorMap::value_type (connector,
+					       OutputSubconnectorInfo (s, bi)));
+	  }
+
+	// register output group
+	std::vector<int>& worldRanks = (*rankMap) [outputLeader];
+	registerGroup (outputLeader, worldRanks);
+
+	// setup Block array
+	Blocks::iterator pos = getBlock (outputLeader);
+	if (pos == block_.end () || pos->rank () != outputLeader)
+	  {
+	    // outputLeader not found in block_
+	    // fill it in, creating one new Block for each rank
+	    // with one BufferInfo per Block
+	    int i = 0;
+	    for (BufferInfos::iterator bi = isi.begin ();
+		 bi != isi.end ();
+		 ++bi, ++i)
+	      {
+		int worldRank = worldRanks[i];
+		pos = getBlock (worldRank);
+		int offset = pos - block_.begin ();
+		block_.insert (pos, Block ());
+		pos = block_.begin () + offset;
+		pos->setRank (worldRank);
+		pos->push_back (&*bi);
+	      }
+	  }
+	else
+	  {
+	    // outputLeader's group of ranks already had Blocks in block_
+	    // Insert one BufferInfo per Block
+	    int i = 0;
+	    for (BufferInfos::iterator bi = isi.begin ();
+		 bi != isi.end ();
+		 ++bi, ++i)
+	      {
+		getBlock (worldRanks[i])->push_back (&*bi);
+	      }
+	  }
+
+	// register input group
+	worldRanks = (*rankMap) [inputLeader];
+	registerGroup (inputLeader, worldRanks);
+
+	pos = getBlock (inputLeader);
+	if (pos == block_.end () || pos->rank () != inputLeader)
+	  {
+	    // inputLeader's group of ranks were not represented in block_
+	    // Create empty Block:s for them
+	    for (int i = 0; i < inputSize; ++i)
+	      {
+		int worldRank = worldRanks[i];
+		pos = getBlock (worldRank);
+		int offset = pos - block_.begin ();
+		block_.insert (pos, Block ());
+		pos = block_.begin () + offset;
+		pos->setRank (worldRank);
+	      }
+	  }
+
+      }
+
+#if 0
+    {
+      std::ostringstream ostr;
+      ostr << "Rank " << MPI::COMM_WORLD.Get_rank () << ": block_ ranks ";
+      for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
+	ostr << b->rank () << ' ';
+      std::cout << ostr.str () << std::endl;
+    }
+#endif
+
+    delete rankMap;
+
+    // setup Block and BufferInfo fields
+
+    unsigned int start = 0;
+
+    // reserve space for error block staging area
+    for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
+      start = std::max (start, b->headerSize ());
+
+    MPI::COMM_WORLD.Allreduce (MPI::IN_PLACE, &start, 1, MPI::UNSIGNED,
+			       MPI::MAX);
+
+    errorBlockSize_ = start;
+
+    for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
+      {
+	b->setStart (start);
+	start += sizeof (HeaderType); // error flag
+	unsigned int size = b->headerSize ();
+	if (size < errorBlockSize_)
+	  {
+	    start += errorBlockSize_ - size; // add some slack
+	    size = errorBlockSize_;
+	  }
+	b->setSize (size);
+	for (BufferInfoPtrs::iterator bi = b->begin (); bi != b->end (); ++bi)
+	  {
+	    start += sizeof (HeaderType); // data size field
+	    (*bi)->setStart (start);
+	    (*bi)->setSize (0);
+	  }
+      }
+
+    // allocate buffer
+    size_ = start;
+    buffer_ = BufferType (malloc (size_));
+    
+    // clear flags in staging area
+    clearFlags ();
+
+    // write header fields into buffer
+    for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
+      {
+	b->clearBufferFlags (buffer_);
+	for (BufferInfoPtrs::iterator bi = b->begin (); bi != b->end (); ++bi)
+	  (*bi)->writeDataSize (buffer_, 0);
+      }
+  }
+
+
+  void
+  MultiBuffer::setupRankMap (int localRank, RankMap* rankMap)
+  {
+    int worldRank = MPI::COMM_WORLD.Get_rank ();
+    int worldSize = MPI::COMM_WORLD.Get_size ();
+    std::vector<RankInfo> rankInfos (worldSize);
+    rankInfos[worldRank] = RankInfo (localLeader_, localRank);
+    MPI::COMM_WORLD.Allgather (MPI::IN_PLACE, 0, MPI::DATATYPE_NULL,
+			       &rankInfos.front (),
+			       sizeof (RankInfo) / sizeof (int),
+			       MPI::INT);
+    for (int wr = 0; wr < worldSize; ++wr)
+      {
+	RankInfo& ri = rankInfos[wr];
+	std::vector<int>& worldRanks = (*rankMap)[ri.leader];
+	if (worldRanks.size () <= static_cast<unsigned int> (ri.localRank))
+	  worldRanks.resize (ri.localRank + 1);
+	worldRanks[ri.localRank] = wr;
+      }
+  }
+
+
+  void
+  MultiBuffer::registerGroup (unsigned int leader,
+			      std::vector<int>& worldRanks)
+  {
+    if (groupMap_.find (leader) == groupMap_.end ())
+      {
+	Intervals& ivals = groupMap_[leader];
+	assert (!worldRanks.empty ());
+	std::vector<int>::iterator wr = worldRanks.begin ();
+	int first = *wr;
+	int last = first;
+	for (++wr; wr != worldRanks.end (); ++wr)
+	  if (*wr == last + 1)
+	    last = *wr;
+	  else
+	    {
+	      ivals.push_back (Interval (first, last));
+	      first = last = *wr;
+	    }
+	ivals.push_back (Interval (first, last));
+      }
+  }
+
+
+  unsigned int
+  MultiBuffer::computeSize (bool twostage)
+  {
+    // compute required total size
+    unsigned int summedSize = 0;
+    unsigned int thisRankSize = 0;
+    int thisRank = MPI::COMM_WORLD.Get_rank ();
+    for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
+      {
+	unsigned int size;
+	if (!twostage && !b->errorFlag (buffer_))
+	  size = b->size ();
+	else
+	  {
+	    // this block requires more space
+	    unsigned int blockSize = sizeof (HeaderType); // error flag
+	    int i = 0;
+	    for (BufferInfoPtrs::iterator bi = b->begin ();
+		 bi != b->end ();
+		 ++bi, ++i)
+	      {
+		blockSize += sizeof (HeaderType); // size field
+		unsigned int requested = b->requestedDataSize (buffer_, i);
+		if (requested > (*bi)->size ())
+		  {
+		    blockSize += requested;
+		  }
+		else
+		  blockSize += (*bi)->size ();
+	      }
+	    size = std::max (errorBlockSize_, blockSize);
+	  }
+	summedSize += size;
+	if (b->rank () == thisRank)
+	  thisRankSize = size;
+      }
+    return thisRankSize + summedSize;
+  }
+
+
+  void
+  MultiBuffer::restructure (bool twostage)
+  {
+    unsigned int size = computeSize (twostage);
+    // resize multi-buffer
+    if (size > size_)
+      {
+	buffer_ = BufferType (realloc (buffer_, size));
+	size_ = size;
+      }
+
+    // relocate buffers
+    unsigned int newStart = size;
+    for (Blocks::reverse_iterator b = block_.rbegin ();
+	 b != block_.rend ();
+	 ++b)
+      {
+	if (!twostage && !b->errorFlag (buffer_))
+	  {
+	    // move entire block with one memmove
+	    newStart -= b->size ();
+	    unsigned int oldStart = b->start ();
+	    unsigned int offset = newStart - oldStart;
+	    if (offset == 0)
+	      break; // we know that there are no further error flags set
+	    memmove (buffer_ + newStart, buffer_ + oldStart, b->size ());
+	    b->setStart (newStart);
+	    for (BufferInfoPtrs::iterator bi = b->begin ();
+		 bi != b->end ();
+		 ++bi)
+	      (*bi)->setStart ((*bi)->start () + offset);
+	  }
+	else
+	  {
+	    unsigned int lastStart = newStart;
+	    // at least one of the buffers requires more storage
+	    int i = b->nBuffers () - 1;
+	    for (BufferInfoPtrs::reverse_iterator bi
+		   = b->rbegin ();
+		 bi != b->rend ();
+		 ++bi, --i)
+	      {
+		unsigned int oldPos = (*bi)->start () - sizeof (HeaderType);
+		unsigned int oldSize = (*bi)->size ();
+		unsigned int requested = b->requestedDataSize (buffer_, i);
+		if (requested > oldSize)
+		  (*bi)->setSize (requested);
+		newStart -= (*bi)->size ();
+		(*bi)->setStart (newStart);
+		newStart -= sizeof (HeaderType);
+		// only touch buffer contents if the block belongs to
+		// current rank => error staging area is used for
+		// requested buffer sizes and buffer contains output
+		// data
+		if (b->rank () == MPI::COMM_WORLD.Get_rank ()
+		    && newStart > oldPos)
+		  memmove (buffer_ + newStart,
+			   buffer_ + oldPos,
+			   oldSize + sizeof (HeaderType));
+	      }
+	    newStart -= sizeof (HeaderType); // error flag
+	    *headerPtr (buffer_ + newStart)
+	      = *headerPtr (buffer_ + b->start ());
+	    unsigned int blockSize = lastStart - newStart;
+	    if (blockSize < errorBlockSize_)
+	      {
+		newStart -= errorBlockSize_ - blockSize;
+		blockSize = errorBlockSize_;
+	      }
+	    b->setStart (newStart);
+	    b->setSize (blockSize);
+	    b->clearBufferErrorFlag (buffer_);
+	  }
+      }
+    clearErrorFlag ();
+
+    // update all existing multiConnectors
+    for (std::vector<Updateable*>::iterator c = multiConnectors.begin ();
+	 c != multiConnectors.end ();
+	 ++c)
+      (*c)->update ();
+  }
+
+  
+  MultiBuffer::Blocks::iterator
+  MultiBuffer::getBlock (int rank)
+  {
+    // binary search (modified from Wikipedia)
+    int imin = 0;
+    int imax = block_.size () - 1;
+    while (imax >= imin)
+      {
+	/* calculate the midpoint for roughly equal partition */
+	int imid = (imin + imax) / 2;
+ 
+	// determine which subarray to search
+	if (block_[imid].rank () < rank)
+	  // change min index to search upper subarray
+	  imin = imid + 1;
+	else if (block_[imid].rank () > rank)
+	  // change max index to search lower subarray
+	  imax = imid - 1;
+	else
+	  // block found at index imid
+	  return block_.begin () + imid;
+      }
+    // rank not found---return position where rank should be inserted
+    return block_.begin () + imin;
+  }
+
+  MultiBuffer::InputSubconnectorInfo*
+  MultiBuffer::getInputSubconnectorInfo (Connector* connector)
+  {
+    InputConnectorMap::iterator pos = inputConnectorMap_.find (connector);
+    assert (pos != inputConnectorMap_.end ());
+    return &pos->second;
+  }
+
+
+  MultiBuffer::OutputSubconnectorInfo*
+  MultiBuffer::getOutputSubconnectorInfo (Connector* connector)
+  {
+    OutputConnectorMap::iterator pos = outputConnectorMap_.find (connector);
+    assert (pos != outputConnectorMap_.end ());
+    return &pos->second;
+  }
+
+
+  void
+  MultiBuffer::dumpBlocks ()
+  {
+    for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
+      std::cout << b->rank () << std::endl;
+  }
+
+
+  /********************************************************************
+   *
+   * MultiConnector
+   *
+   ********************************************************************/
+
+  MultiConnector::MultiConnector (MultiBuffer* multiBuffer)
+    : multiBuffer_ (multiBuffer),
+      recvcountInvalid_ (false)
+  {
+    connectorCode_ = ConnectorInfo::allocPortCode ();
+    buffer_ = multiBuffer_->buffer ();
+    groupMap_ = new GroupMap;
+    multiBuffer_->addMultiConnector (this);
+  }
+
+  //*fixme* code repetition
+  MultiConnector::MultiConnector (MultiBuffer* multiBuffer,
+				  std::vector<Connector*>& connectors)
+    : multiBuffer_ (multiBuffer),
+      recvcountInvalid_ (false)
+  {
+    buffer_ = multiBuffer_->buffer ();
+    groupMap_ = new GroupMap;
+    multiBuffer_->addMultiConnector (this);
+    for (std::vector<Connector*>::iterator c = connectors.begin ();
+	 c != connectors.end ();
+	 ++c)
+      add (*c);
+    initialize ();
+  }
+
+  void
+  MultiConnector::mergeGroup (int leader, bool isInput)
+  {
+    if (groupMap_->find (leader) == groupMap_->end ())
+      {
+	MCGroupInfo& g = (*groupMap_)[leader];
+	g.worldRankIntervals = &multiBuffer_->getWorldRankIntervals (leader);
+	g.blank = isInput;
+      }
+    else
+      // Only groups which provide output communicate.  Groups which
+      // only have inputs are blanked.  "Blanked" means that the
+      // corresponding recvcount in Allgather is 0.
+      (*groupMap_)[leader].blank &= isInput;
+  }
+
+  void
+  MultiConnector::add (Connector* connector)
+  {
+    if (connector->isInput ())
+      {
+	// The following has to be done here so that multiConnector
+	// groups are created the same way in all applications.
+	//
+	// BUT: Do we need to sort the connectors? We do if the
+	// scheduler can deliver connectors in different order in
+	// different applications.
+	connectorIds_.push_back (std::make_pair (connector->remoteLeader (),
+						 multiBuffer_->localLeader ()));
+	mergeGroup (multiBuffer_->localLeader (), true);
+	mergeGroup ((connector)->remoteLeader (), false);
+	inputSubconnectorInfo_.push_back (multiBuffer_
+					  ->getInputSubconnectorInfo (connector));
+      }
+    else
+      {
+	connectorIds_.push_back (std::make_pair (multiBuffer_->localLeader (),
+						 connector->remoteLeader ()));
+	mergeGroup ((connector)->remoteLeader (), true);
+	mergeGroup (multiBuffer_->localLeader (), false);
+	outputSubconnectorInfo_.push_back (multiBuffer_
+					   ->getOutputSubconnectorInfo (connector));
+      }
+  }
+
+  void
+  MultiConnector::initialize ()
+  {
+    bool isContiguous = true;
+    {
+#ifdef MUSIC_DEBUG
+      std::ostringstream ostr;
+      ostr << "Rank " << MPI::COMM_WORLD.Get_rank () << ": Create ";
+#endif
+      int nRanges = 0;
+      for (GroupMap::iterator g = groupMap_->begin ();
+	   g != groupMap_->end ();
+	   ++g)
+	nRanges += g->second.worldRankIntervals->size ();
+
+      int (*range)[3] = new int[nRanges][3];
+      int i = 0;
+      for (GroupMap::iterator g = groupMap_->begin ();
+	   g != groupMap_->end ();
+	   ++g)
+	{
+	  int leader = g->first;
+	  Intervals& ivals = *g->second.worldRankIntervals;
+#ifdef MUSIC_DEBUG
+	  ostr << leader << ", ";
+#endif
+	  int size = 0;
+	  int next = ivals[0].first;
+	  for (Intervals::iterator ival = ivals.begin ();
+	       ival != ivals.end ();
+	       ++ival)
+	    {
+	      range[i][0] = ival->first;
+	      range[i][1] = ival->last;
+	      range[i][2] = 1;
+	      ++i;
+	      if (ival->first != next)
+		isContiguous = false;
+	      next = ival->last + 1;
+	      size += ival->last - ival->first + 1;
+	    }
+	  g->second.size = size;
+	}
+#ifdef MUSIC_DEBUG
+      ostr << std::endl;
+      std::cout << ostr.str () << std::flush;
+#endif
+      group_ = MPI::COMM_WORLD.Get_group ().Range_incl (nRanges, range);
+      delete[] range;
+    }
+
+    sort (connectorIds_.begin (), connectorIds_.end ());
+    std::ostringstream idstr_;
+    std::vector<std::pair<int, int> >::iterator cid = connectorIds_.begin ();
+    idstr_ << cid->first << cid->second;
+    ++cid;
+    for (; cid != connectorIds_.end (); ++cid)
+      idstr_ << ':' << cid->first << cid->second;
+    id_ = "mc" + idstr_.str ();
+
+    if (!isContiguous || group_.Get_size () < MPI::COMM_WORLD.Get_size ())
+      comm_ = MPI::COMM_WORLD.Create (group_);
+    else
+      comm_ = MPI::COMM_WORLD;
+    MPI::COMM_WORLD.Barrier ();
+
+    std::vector<int> ranks (size ());
+    std::vector<int> indices (size ());
+    for (int rank = 0; rank < size (); ++rank)
+      ranks[rank] = rank;
+    MPI::Group::Translate_ranks (group_, size (), &ranks[0],
+				 MPI::COMM_WORLD.Get_group (), &indices[0]);
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+    twostage_ = true;
+#endif
+    for (int rank = 0; rank < size (); ++rank)
+      {
+	Blocks::iterator b = multiBuffer_->getBlock (indices[rank]);
+#ifdef MUSIC_DEBUG
+	if (b == multiBuffer_->blockEnd () && MPI::COMM_WORLD.Get_rank () == 0)
+	  {
+	    std::cout << "asked for rank " << indices[rank] << " among:" << std::endl;
+	    multiBuffer_->dumpBlocks ();
+	  }
+#endif
+	assert (b != multiBuffer_->blockEnd ());
+	block_.push_back (&*b);
+	
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+	// *fixme* need better criterion in the case of MC:s with
+	// proxy connectors
+	if (b->nBuffers () > 1)
+	  twostage_ = false;
+	else if (twostage_ && b->nBuffers () > 0)
+	  {
+	    BufferInfo* bi = *b->begin ();
+	    // Should store this information in separate data structure
+	    bi->setRank (rank);
+	  }
+#endif
+      }
+
+    recvcounts_ = new int[size ()];
+    displs_ = new int[size ()];
+
+    blank_ = new bool[size ()];
+    int i = 0;
+    for (GroupMap::iterator g = groupMap_->begin ();
+	 g != groupMap_->end ();
+	 ++g)
+      {
+	int leader = g->first;
+	int size = (*groupMap_)[leader].size;
+	int limit = i + size;
+	for (; i < limit; ++i)
+	  blank_[i] = g->second.blank;
+      }
+    assert (i == size ());
+    delete groupMap_;
+
+    restructuring_ = true;
+    update ();
+    restructuring_ = false;
+  }
+
+
+  void
+  MultiConnector::update ()
+  {
+    buffer_ = multiBuffer_->buffer ();
+    for (OutputSubconnectorInfos::iterator osi
+	   = outputSubconnectorInfo_.begin ();
+	 osi != outputSubconnectorInfo_.end ();
+	 ++osi)
+      {
+	unsigned int dataSize = (*osi)->subconnector ()->dataSize ();
+	BufferInfo* bi = (*osi)->bufferInfo ();
+	bi->writeDataSize (buffer_, dataSize);
+	(*osi)->subconnector ()->setOutputBuffer (buffer_
+						  + bi->start (),
+						  bi->size ());
+      }
+    for (int r = 0; r < size (); ++r)
+      {
+	Block* block = block_[r];
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+	if (twostage_)
+	  {
+	    if (block->begin () != block->end ())
+	      displs_[r] = (*block->begin ())->start ();
+	    else
+	      displs_[r] = 0;
+	  }
+	else
+#endif
+	  {
+	    int newRecvcount = blank_[r] ? 0 : block->size ();
+	    if (!restructuring_ && r == rank () && newRecvcount > recvcounts_[r])
+	      // Another MultiConnector has caused MultiBuffer
+	      // restructuring.  We need to postpone modifying recvcount
+	      // until our partner knows the new size.
+	      recvcountInvalid_ = true;
+	    else
+	      recvcounts_[r] = newRecvcount;
+	    displs_[r] = block->start ();
+	  }
+      }
+  }
+
+
+  bool
+  MultiConnector::writeSizes ()
+  {
+    bool dataFits = true;
+    for (OutputSubconnectorInfos::iterator osi
+	   = outputSubconnectorInfo_.begin ();
+	 osi != outputSubconnectorInfo_.end ();
+	 ++osi)
+      {
+	(*osi)->subconnector ()->nextBlock ();
+	unsigned int dataSize = (*osi)->subconnector ()->dataSize ();
+	if (!recvcountInvalid_)
+	  (*osi)->bufferInfo ()->writeDataSize (buffer_, dataSize);
+	if (dataSize > (*osi)->bufferInfo ()->size ())
+	    dataFits = false;
+      }
+    if (recvcountInvalid_ // another MultiConnector caused restructuring
+	|| !dataFits)
+      {
+	displs_[rank ()] = 0; // error block staging area
+	multiBuffer_->setErrorFlag ();
+	int i = 0;
+	for (OutputSubconnectorInfos::iterator osi
+	       = outputSubconnectorInfo_.begin ();
+	     osi != outputSubconnectorInfo_.end ();
+	     ++osi, ++i)
+	  {
+	    unsigned int size = (*osi)->bufferInfo ()->size ();
+	    unsigned int dataSize = (*osi)->subconnector ()->dataSize ();
+	    multiBuffer_->writeRequestedDataSize (i, std::max (size, dataSize));
+	  }
+	return false;
+      }
+    return true;
+  }
+
+
+  void
+  MultiConnector::fillBuffers ()
+  {
+    for (OutputSubconnectorInfos::iterator osi
+	   = outputSubconnectorInfo_.begin ();
+	 osi != outputSubconnectorInfo_.end ();
+	 ++osi)
+      (*osi)->subconnector ()->fillOutputBuffer ();
+  }
+
+
+  void
+  MultiConnector::processInput ()
+  {
+    for (InputSubconnectorInfoPtrs::iterator isi
+	   = inputSubconnectorInfo_.begin ();
+	 isi != inputSubconnectorInfo_.end ();
+	 ++isi)
+      {
+	InputSubconnector* subconnector = (*isi)->subconnector ();
+	for (BufferInfos::iterator bi = (*isi)->begin ();
+	     bi != (*isi)->end ();
+	     ++bi)
+	  subconnector->processData (buffer_ + bi->start (),
+				     bi->readDataSize (buffer_));
+      }
+  }
+
+
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+  void
+  MultiConnector::processReceived ()
+  {
+    for (InputSubconnectorInfoPtrs::iterator isi
+	   = inputSubconnectorInfo_.begin ();
+	 isi != inputSubconnectorInfo_.end ();
+	 ++isi)
+      {
+	InputSubconnector* subconnector = (*isi)->subconnector ();
+	for (BufferInfos::iterator bi = (*isi)->begin ();
+	     bi != (*isi)->end ();
+	     ++bi)
+	  subconnector->processData (buffer_ + bi->start (),
+				     recvcounts_[bi->rank ()]);
+      }
+  }
+
+
+  void
+  MultiConnector::checkRestructure ()
+  {
+    bool dataFits = true;
+    doAllgather_ = false;
+    int r = 0;
+    for (BlockPtrs::iterator b = block_.begin ();
+	 b != block_.end ();
+	 ++r, ++b)
+      {
+	int size = recvcounts_[r];
+	if (size)
+	  doAllgather_ = true;
+	if (size & TWOSTAGE_FINALIZE_FLAG)
+	  {
+	    block_[r]->setFinalizeFlag (buffer_);
+	    recvcounts_[r] &= ~TWOSTAGE_FINALIZE_FLAG;
+	  }
+	BufferInfoPtrs::iterator bipi = (*b)->begin ();
+	if (bipi != (*b)->end ())
+	  {
+	    BufferInfo* bi = *bipi;
+	    if (size > bi->size ())
+	      dataFits = false;
+	  }
+      }
+    if (!dataFits)
+      {
+	int r = 0;
+	for (BlockPtrs::iterator b = block_.begin ();
+	     b != block_.end ();
+	     ++r, ++b)
+	  {
+	    BufferInfoPtrs::iterator bipi = (*b)->begin ();
+	    if (bipi != (*b)->end ())
+	      {
+		int size = recvcounts_[r];
+		BufferInfo* bi = *bipi;
+		if (size < bi->size ())
+		  size = bi->size ();
+		bi->writeDataSize (buffer_, size);
+	      }
+	  }
+	BufferInfoPtrs::iterator bipi = block_[rank()]->begin ();
+	int bsize = 0;
+	if (bipi != block_[rank ()]->end ())
+	  bsize = (*bipi)->size ();
+	multiBuffer_->writeRequestedDataSize (0,
+					      std::max (recvcounts_[rank ()],
+							bsize));
+	multiBuffer_->restructure (true);
+      }
+  }  
+#endif
+
+
+  static void
+  dumprecvc (std::string id, int* recvc, int* displs, int n)
+  {
+    std::ostringstream ostr;
+#if 1
+    ostr << "Rank " << MPI::COMM_WORLD.Get_rank () << ": "
+	 << id << ": Allgather " << *recvc;
+    for (int i = 1; i < n; ++i)
+      ostr << ", " << recvc[i];
+#else
+    ostr << "Rank " << MPI::COMM_WORLD.Get_rank () << ": "
+	 << id << ": Allgather "
+	 << *displs << ':' << *recvc;
+    for (int i = 1; i < n; ++i)
+      ostr << ", " << displs[i] << ':' << recvc[i];
+#endif
+    ostr << std::endl;
+    std::cout << ostr.str () << std::flush;
+  }
+
+
+  void
+  MultiConnector::tick ()
+  {
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+    if (twostage_)
+      {
+	// *fixme* nextBlock ()
+	OutputSubconnectorInfos::iterator osi = outputSubconnectorInfo_.begin ();
+	int recvc;
+	if (osi != outputSubconnectorInfo_.end ())
+	  recvc = (*osi)->subconnector ()->dataSize ();
+	else
+	  recvc = 0;
+	if (block_[rank ()]->finalizeFlag (buffer_))
+	  recvc |= TWOSTAGE_FINALIZE_FLAG;
+	recvcounts_[rank ()] = recvc;
+	comm_.Allgather (MPI::IN_PLACE, 0, MPI::DATATYPE_NULL,
+			 recvcounts_, 1, MPI::INT);
+	checkRestructure (); // sets doAllgather_
+	if (doAllgather_)
+	  {
+	    fillBuffers ();
+#ifdef MUSIC_DEBUG
+	    dumprecvc (id_, recvcounts_, displs_, comm_.Get_size ());
+#endif
+	    comm_.Allgatherv (MPI::IN_PLACE, 0, MPI::DATATYPE_NULL,
+			      buffer_, recvcounts_, displs_, MPI::BYTE);
+	    processReceived ();
+	  }
+      }
+    else
+#endif
+      {
+	if (writeSizes ())
+	  // Data will fit
+	  fillBuffers ();
+#ifdef MUSIC_DEBUG
+	dumprecvc (id_, recvcounts_, displs_, comm_.Get_size ());
+#endif
+	comm_.Allgatherv (MPI::IN_PLACE, 0, MPI::DATATYPE_NULL,
+			  buffer_, recvcounts_, displs_, MPI::BYTE);
+	for (BlockPtrs::iterator b = block_.begin ();
+	     b != block_.end ();
+	     ++b)
+	  if ((*b)->errorFlag (buffer_))
+	    {
+	      restructuring_ = true;
+	      multiBuffer_->restructure (false);
+	      restructuring_ = false;
+	      recvcountInvalid_ = false;
+	      fillBuffers ();
+#ifdef MUSIC_DEBUG
+	      dumprecvc (id_, recvcounts_, displs_, comm_.Get_size ());
+#endif
+	      comm_.Allgatherv (MPI::IN_PLACE, 0, MPI::DATATYPE_NULL,
+				buffer_, recvcounts_, displs_, MPI::BYTE);
+	      break;
+	    }
+	processInput ();
+      }
+  }
+
+
+  bool
+  MultiConnector::isFinalized ()
+  {
+    bool finalized = true;
+    for (int i = 0; i < size (); ++i)
+      if (!blank_[i] && !block_[i]->finalizeFlag (buffer_))
+	finalized = false;
+    return finalized;
+  }
+
+
+  void
+  MultiConnector::finalize ()
+  {
+    if (!blank_[rank ()])
+      block_[rank ()]->setFinalizeFlag (buffer_);
+  }
+
+}
+
+#endif // MUSIC_USE_MPI
diff --git a/src/music-c-c.c b/src/music-c-c.c
new file mode 100644
index 0000000..b23cdfa
--- /dev/null
+++ b/src/music-c-c.c
@@ -0,0 +1,15 @@
+
+#if MUSIC_USE_MPI
+#include <mpi.h>
+#include "music-c.h"
+
+/* Communicators */
+
+MPI_Comm MUSIC_setupCommunicatorGlue (MUSIC_Setup *setup);
+
+MPI_Comm
+MUSIC_setupCommunicator (MUSIC_Setup *setup)
+{
+  return (MPI_Comm) MUSIC_setupCommunicatorGlue (setup);
+}
+#endif
diff --git a/src/music-c.cc b/src/music-c.cc
new file mode 100644
index 0000000..73d8045
--- /dev/null
+++ b/src/music-c.cc
@@ -0,0 +1,519 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "music.hh"
+#if MUSIC_USE_MPI
+
+
+#include <string>
+#include <cstring>
+
+extern "C" {
+
+#include "music-c.h"
+
+/* Setup */
+
+MUSIC_Setup *
+MUSIC_createSetup (int *argc, char ***argv)
+{
+  return (MUSIC_Setup *) new MUSIC::Setup (*argc, *argv);
+}
+
+
+MUSIC_Setup *
+MUSIC_createSetupThread (int *argc, char ***argv, int required, int *provided)
+{
+  return (MUSIC_Setup *) new MUSIC::Setup (*argc, *argv, required, provided);
+}
+
+
+/* Communicators */
+
+MPI_Comm
+MUSIC_setupCommunicatorGlue (MUSIC_Setup *setup)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return (MPI_Comm) cxxSetup->communicator ();
+}
+
+
+/* Port creation */
+
+MUSIC_ContOutputPort *
+MUSIC_publishContOutput (MUSIC_Setup *setup, char *id)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return (MUSIC_ContOutputPort *) cxxSetup->publishContOutput (id);
+}
+
+
+MUSIC_ContInputPort *
+MUSIC_publishContInput (MUSIC_Setup *setup, char *id)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return (MUSIC_ContInputPort *) cxxSetup->publishContInput(id);
+}
+
+
+MUSIC_EventOutputPort *
+MUSIC_publishEventOutput (MUSIC_Setup *setup, char *id)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return (MUSIC_EventOutputPort *) cxxSetup->publishEventOutput(id);
+}
+
+
+MUSIC_EventInputPort *
+MUSIC_publishEventInput (MUSIC_Setup *setup, char *id)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return (MUSIC_EventInputPort *) cxxSetup->publishEventInput(id);
+}
+
+
+MUSIC_MessageOutputPort *
+MUSIC_publishMessageOutput (MUSIC_Setup *setup, char *id)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return (MUSIC_MessageOutputPort *) cxxSetup->publishMessageOutput(id);
+}
+
+
+MUSIC_MessageInputPort *
+MUSIC_publishMessageInput (MUSIC_Setup *setup, char *id)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return (MUSIC_MessageInputPort *) cxxSetup->publishMessageInput(id);
+}
+
+/*
+void
+MUSIC_destroyContOutput (MUSIC_ContOutputPort* Port)
+{
+  delete (MUSIC::ContOutputPort *) Port;
+}
+
+
+void
+MUSIC_destroyContInput (MUSIC_ContInputPort* Port)
+{
+  delete (MUSIC::ContInputPort *) Port;
+}
+
+
+void
+MUSIC_destroyEventOutput (MUSIC_EventOutputPort* Port)
+{
+  delete (MUSIC::EventOutputPort *) Port;
+}
+
+
+void
+MUSIC_destroyEventInput (MUSIC_EventInputPort* Port)
+{
+  delete (MUSIC::EventInputPort *) Port;
+}
+
+
+void
+MUSIC_destroyMessageOutput (MUSIC_MessageOutputPort* Port)
+{
+  delete (MUSIC::MessageOutputPort *) Port;
+}
+
+
+void
+MUSIC_destroyMessageInput (MUSIC_MessageInputPort* Port)
+{
+  delete (MUSIC::MessageInputPort *) Port;
+}
+*/
+
+/* General port methods */
+
+int
+MUSIC_ContOutputPort_isConnected (MUSIC_ContOutputPort *Port)
+{
+  MUSIC::ContOutputPort* cxxPort = (MUSIC::ContOutputPort *) Port;
+  return cxxPort->isConnected ();
+}
+
+
+int
+MUSIC_ContInputPort_isConnected (MUSIC_ContInputPort *Port)
+{
+  MUSIC::ContInputPort* cxxPort = (MUSIC::ContInputPort *) Port;
+  return cxxPort->isConnected ();
+}
+
+
+int
+MUSIC_EventOutputPort_isConnected (MUSIC_EventOutputPort *Port)
+{
+  MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
+  return cxxPort->isConnected ();
+}
+
+
+int
+MUSIC_EventInputPort_isConnected (MUSIC_EventInputPort *Port)
+{
+  MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
+  return cxxPort->isConnected ();
+}
+
+
+int
+MUSIC_MessageOutputPort_isConnected (MUSIC_MessageOutputPort *Port)
+{
+  MUSIC::MessageOutputPort* cxxPort = (MUSIC::MessageOutputPort *) Port;
+  return cxxPort->isConnected ();
+}
+
+
+int
+MUSIC_MessageInputPort_isConnected (MUSIC_MessageInputPort *Port)
+{
+  MUSIC::MessageInputPort* cxxPort = (MUSIC::MessageInputPort *) Port;
+  return cxxPort->isConnected ();
+}
+
+
+int
+MUSIC_ContOutputPort_hasWidth (MUSIC_ContOutputPort *Port)
+{
+  MUSIC::ContOutputPort* cxxPort = (MUSIC::ContOutputPort *) Port;
+  return cxxPort->hasWidth ();
+}
+
+
+int
+MUSIC_ContInputPort_hasWidth (MUSIC_ContInputPort *Port)
+{
+  MUSIC::ContInputPort* cxxPort = (MUSIC::ContInputPort *) Port;
+  return cxxPort->hasWidth ();
+}
+
+
+int
+MUSIC_EventOutputPort_hasWidth (MUSIC_EventOutputPort *Port)
+{
+  MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
+  return cxxPort->hasWidth ();
+}
+
+
+int
+MUSIC_EventInputPort_hasWidth (MUSIC_EventInputPort *Port)
+{
+  MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
+  return cxxPort->hasWidth ();
+}
+
+
+int
+MUSIC_ContOutputPort_width (MUSIC_ContOutputPort *Port)
+{
+  MUSIC::ContOutputPort* cxxPort = (MUSIC::ContOutputPort *) Port;
+  return cxxPort->width ();
+}
+
+
+int
+MUSIC_ContInputPort_width (MUSIC_ContInputPort *Port)
+{
+  MUSIC::ContInputPort* cxxPort = (MUSIC::ContInputPort *) Port;
+  return cxxPort->width ();
+}
+
+
+int
+MUSIC_EventOutputPort_width (MUSIC_EventOutputPort *Port)
+{
+  MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
+  return cxxPort->width ();
+}
+
+
+int
+MUSIC_EventInputPort_width (MUSIC_EventInputPort *Port)
+{
+  MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
+  return cxxPort->width ();
+}
+
+
+/* Mapping */
+
+/* No arguments are optional. */
+
+void
+MUSIC_ContOutputPort_map (MUSIC_ContOutputPort *Port,
+			  MUSIC_ContData *dmap,
+			  int maxBuffered)
+{
+  MUSIC::ContOutputPort* cxxPort = (MUSIC::ContOutputPort *) Port;
+  MUSIC::ContData* cxxDmap = (MUSIC::ContData *) dmap;
+  cxxPort->map (cxxDmap, maxBuffered);
+}
+
+
+void
+MUSIC_ContInputPort_map (MUSIC_ContInputPort *Port,
+			 MUSIC_ContData *dmap,
+			 double delay,
+			 int maxBuffered,
+			 int interpolate)
+{
+  MUSIC::ContInputPort* cxxPort = (MUSIC::ContInputPort *) Port;
+  MUSIC::ContData* cxxDmap = (MUSIC::ContData *) dmap;
+  cxxPort->map (cxxDmap, delay, maxBuffered, interpolate);
+}
+
+
+void
+MUSIC_EventOutputPort_mapGlobalIndex (MUSIC_EventOutputPort *Port,
+				      MUSIC_IndexMap *indices,
+				      int maxBuffered)
+{
+  MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
+  MUSIC::IndexMap* cxxIndices = (MUSIC::IndexMap *) indices;
+  cxxPort->map (cxxIndices, MUSIC::Index::GLOBAL, maxBuffered);
+}
+
+
+void
+MUSIC_EventOutputPort_mapLocalIndex (MUSIC_EventOutputPort *Port,
+				     MUSIC_IndexMap *indices,
+				     int maxBuffered)
+{
+  MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
+  MUSIC::IndexMap* cxxIndices = (MUSIC::IndexMap *) indices;
+  cxxPort->map (cxxIndices, MUSIC::Index::LOCAL, maxBuffered);
+}
+
+
+typedef void MUSIC_EventHandler (double t, int id);
+
+void
+MUSIC_EventInputPort_mapGlobalIndex (MUSIC_EventInputPort *Port,
+				     MUSIC_IndexMap *indices,
+				     MUSIC_EventHandler *handleEvent,
+				     double accLatency,
+				     int maxBuffered)
+{
+  MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
+  MUSIC::IndexMap* cxxIndices = (MUSIC::IndexMap *) indices;
+  MUSIC::EventHandlerGlobalIndexProxy* cxxHandleEvent =
+    cxxPort->allocEventHandlerGlobalIndexProxy (handleEvent);
+  cxxPort->map (cxxIndices, cxxHandleEvent, accLatency, maxBuffered);
+}
+
+
+void
+MUSIC_EventInputPort_mapLocalIndex (MUSIC_EventInputPort *Port,
+				    MUSIC_IndexMap *indices,
+				    MUSIC_EventHandler *handleEvent,
+				    double accLatency,
+				    int maxBuffered)
+{
+  MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
+  MUSIC::IndexMap* cxxIndices = (MUSIC::IndexMap *) indices;
+  MUSIC::EventHandlerLocalIndexProxy* cxxHandleEvent =
+    cxxPort->allocEventHandlerLocalIndexProxy (handleEvent);
+  cxxPort->map (cxxIndices, cxxHandleEvent, accLatency, maxBuffered);
+}
+
+
+void
+MUSIC_MessageOutputPort_map_no_handler (MUSIC_MessageOutputPort *Port)
+{
+  MUSIC::MessageOutputPort* cxxPort = (MUSIC::MessageOutputPort *) Port;
+  cxxPort->map ();
+}
+
+
+void
+MUSIC_MessageOutputPort_map (MUSIC_MessageOutputPort *Port,
+			     int maxBuffered)
+{
+  MUSIC::MessageOutputPort* cxxPort = (MUSIC::MessageOutputPort *) Port;
+  cxxPort->map (maxBuffered);
+}
+
+
+typedef void MUSIC_MessageHandler (double t, void *msg, size_t size);
+
+void
+MUSIC_MessageInputPort_map (MUSIC_MessageInputPort *Port,
+			    MUSIC_MessageHandler *handleMessage,
+			    double accLatency,
+			    int maxBuffered)
+{
+  MUSIC::MessageInputPort* cxxPort = (MUSIC::MessageInputPort *) Port;
+  MUSIC::MessageHandlerProxy* cxxHandleMessage =
+    cxxPort->allocMessageHandlerProxy (handleMessage);
+  cxxPort->map (cxxHandleMessage, accLatency, maxBuffered);
+}
+
+
+/* Index maps */
+
+MUSIC_PermutationIndex *
+MUSIC_createPermutationIndex (int *indices,
+			      int size)
+{
+  void* data = static_cast<void*> (indices);
+  return (MUSIC_PermutationIndex *)
+    new MUSIC::PermutationIndex (static_cast<MUSIC::GlobalIndex*> (data),
+				  size);
+}
+
+
+void
+MUSIC_destroyPermutationIndex (MUSIC_PermutationIndex *Index)
+{
+  delete (MUSIC::PermutationIndex *) Index;
+}
+
+
+MUSIC_LinearIndex *
+MUSIC_createLinearIndex (int baseIndex,
+			 int size)
+{
+  return (MUSIC_LinearIndex *) new MUSIC::LinearIndex (baseIndex, size);
+}
+
+
+void
+MUSIC_destroyLinearIndex (MUSIC_LinearIndex *Index)
+{
+  delete (MUSIC::LinearIndex *) Index;
+}
+
+
+/* Data maps */
+
+/* Exception: The map argument can take any type of index map. */
+
+MUSIC_ArrayData *
+MUSIC_createArrayData (void *buffer,
+		       MPI_Datatype type,
+		       void *map)
+{
+  MUSIC::IndexMap* cxxMap = (MUSIC::IndexMap *) map;
+  return (MUSIC_ArrayData *) new MUSIC::ArrayData (buffer, type, cxxMap);
+}
+
+
+/* Exception: MUSIC_createLinearArrayData corresponds to
+   c++ MUSIC::ArrayData::ArrayData (..., ..., ..., ...) */
+
+MUSIC_ArrayData *
+MUSIC_createLinearArrayData (void *buffer,
+			     MPI_Datatype type,
+			     int baseIndex,
+			     int size)
+{
+  return (MUSIC_ArrayData *) new MUSIC::ArrayData (buffer,
+						   type,
+						   baseIndex,
+						   size);
+}
+
+
+void
+MUSIC_destroyArrayData (MUSIC_ArrayData *ArrayData)
+{
+  delete (MUSIC::ArrayData *) ArrayData;
+}
+
+
+/* Configuration variables */
+
+/* Exceptions: Result is char *
+   Extra maxlen argument prevents buffer overflow.
+   Result is terminated by \0 unless longer than maxlen - 1 */
+
+int
+MUSIC_configString (MUSIC_Setup *setup,
+		    char *name,
+		    char *result,
+		    size_t maxlen)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  std::string cxxResult;
+  int res = cxxSetup->config (string (name), &cxxResult);
+  strncpy(result, cxxResult.c_str (), maxlen);
+  return res;
+}
+
+
+int
+MUSIC_configInt (MUSIC_Setup *setup, char *name, int *result)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return cxxSetup->config (string(name), result);
+}
+
+
+int
+MUSIC_configDouble (MUSIC_Setup *setup, char *name, double *result)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return cxxSetup->config (string(name), result);
+}
+
+
+/* Runtime */
+
+MUSIC_Runtime *
+MUSIC_createRuntime (MUSIC_Setup *setup, double h)
+{
+  MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
+  return (MUSIC_Runtime *) new MUSIC::Runtime (cxxSetup, h);
+}
+
+
+void
+MUSIC_tick (MUSIC_Runtime *runtime)
+{
+  MUSIC::Runtime* cxxRuntime = (MUSIC::Runtime *) runtime;
+  cxxRuntime->tick ();
+}
+
+
+double
+MUSIC_time (MUSIC_Runtime *runtime)
+{
+  MUSIC::Runtime* cxxRuntime = (MUSIC::Runtime *) runtime;
+  return cxxRuntime->time ();
+}
+
+
+/* Finalization */
+
+void
+MUSIC_destroyRuntime (MUSIC_Runtime *runtime)
+{
+  MUSIC::Runtime* cxxRuntime = (MUSIC::Runtime *) runtime;
+  delete cxxRuntime;
+}
+
+}
+#endif
diff --git a/src/music-c.h b/src/music-c.h
new file mode 100644
index 0000000..d184dc7
--- /dev/null
+++ b/src/music-c.h
@@ -0,0 +1,209 @@
+#ifndef MUSIC_C_H
+
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "music/music-config.hh"
+
+#if MUSIC_USE_MPI
+#include <mpi.h>
+
+#if MUSIC_HAVE_SIZE_T
+#include <sys/types.h>
+#else
+typedef int size_t;
+#endif
+
+/* Setup */
+
+typedef struct MUSIC_Setup MUSIC_Setup;
+
+MUSIC_Setup *MUSIC_createSetup (int *argc, char ***argv);
+MUSIC_Setup *MUSIC_createSetupThread (int *argc,
+				      char ***argv,
+				      int required,
+				      int* provided);
+
+/* Communicators */
+
+#ifndef BUILDING_MUSIC_LIBRARY
+MPI_Comm MUSIC_setupCommunicator (MUSIC_Setup *setup);
+#endif
+
+/* Ports */
+
+typedef struct MUSIC_ContOutputPort MUSIC_ContOutputPort;
+typedef struct MUSIC_ContInputPort MUSIC_ContInputPort;
+typedef struct MUSIC_EventOutputPort MUSIC_EventOutputPort;
+typedef struct MUSIC_EventInputPort MUSIC_EventInputPort;
+typedef struct MUSIC_MessageOutputPort MUSIC_MessageOutputPort;
+typedef struct MUSIC_MessageInputPort MUSIC_MessageInputPort;
+
+MUSIC_ContOutputPort *MUSIC_publishContOutput (MUSIC_Setup *setup, char *id);
+MUSIC_ContInputPort *MUSIC_publishContInput (MUSIC_Setup *setup, char *id);
+MUSIC_EventOutputPort *MUSIC_publishEventOutput (MUSIC_Setup *setup, char *id);
+MUSIC_EventInputPort *MUSIC_publishEventInput (MUSIC_Setup *setup, char *id);
+MUSIC_MessageOutputPort *MUSIC_publishMessageOutput (MUSIC_Setup *setup, char *id);
+MUSIC_MessageInputPort *MUSIC_publishMessageInput (MUSIC_Setup *setup, char *id);
+
+/* remedius
+ *  Free of the ports is done by the Runtime instance
+ */
+/*void MUSIC_destroyContOutput (MUSIC_ContOutputPort* port);
+void MUSIC_destroyContInput (MUSIC_ContInputPort* port);
+void MUSIC_destroyEventOutput (MUSIC_EventOutputPort* port);
+void MUSIC_destroyEventInput (MUSIC_EventInputPort* port);
+void MUSIC_destroyMessageOutput (MUSIC_MessageOutputPort* port);
+void MUSIC_destroyMessageInput (MUSIC_MessageInputPort* port);
+*/
+/* General port methods */
+
+int MUSIC_ContOutputPort_isConnected (MUSIC_ContOutputPort *port);
+int MUSIC_ContInputPort_isConnected (MUSIC_ContInputPort *port);
+int MUSIC_EventOutputPort_isConnected (MUSIC_EventOutputPort *port);
+int MUSIC_EventInputPort_isConnected (MUSIC_EventInputPort *port);
+int MUSIC_MessageOutputPort_isConnected (MUSIC_MessageOutputPort *port);
+int MUSIC_MessageInputPort_isConnected (MUSIC_MessageInputPort *port);
+int MUSIC_ContOutputPort_hasWidth (MUSIC_ContOutputPort *port);
+int MUSIC_ContInputPort_hasWidth (MUSIC_ContInputPort *port);
+int MUSIC_EventOutputPort_hasWidth (MUSIC_EventOutputPort *port);
+int MUSIC_EventInputPort_hasWidth (MUSIC_EventInputPort *port);
+int MUSIC_ContOutputPort_width (MUSIC_ContOutputPort *port);
+int MUSIC_ContInputPort_width (MUSIC_ContInputPort *port);
+int MUSIC_EventOutputPort_width (MUSIC_EventOutputPort *port);
+int MUSIC_EventInputPort_width (MUSIC_EventInputPort *port);
+
+/* Mapping */
+
+/* Data maps */
+
+typedef struct MUSIC_DataMap MUSIC_DataMap;
+typedef struct MUSIC_ContData MUSIC_ContData;
+typedef struct MUSIC_ArrayData MUSIC_ArrayData;
+
+/* Index maps */
+
+typedef struct MUSIC_IndexMap MUSIC_IndexMap;
+typedef struct MUSIC_PermutationIndex MUSIC_PermutationIndex;
+typedef struct MUSIC_LinearIndex MUSIC_LinearIndex;
+
+
+/* No arguments are optional. */
+
+void MUSIC_ContOutputPort_map (MUSIC_ContOutputPort *port,
+			       MUSIC_ContData *dmap,
+			       int maxBuffered);
+
+void MUSIC_ContInputPort_map (MUSIC_ContInputPort *port,
+			      MUSIC_ContData *dmap,
+			      double delay,
+			      int maxBuffered,
+			      int interpolate);
+
+void MUSIC_EventOutputPort_mapGlobalIndex (MUSIC_EventOutputPort *Port,
+					   MUSIC_IndexMap *indices,
+					   int maxBuffered);
+
+void MUSIC_EventOutputPort_mapLocalIndex (MUSIC_EventOutputPort *Port,
+					  MUSIC_IndexMap *indices,
+					  int maxBuffered);
+
+typedef void MUSIC_EventHandler (double t, int id);
+
+void MUSIC_EventInputPort_mapGlobalIndex (MUSIC_EventInputPort *port,
+					  MUSIC_IndexMap *indices,
+					  MUSIC_EventHandler *handleEvent,
+					  double accLatency,
+					  int maxBuffered);
+
+void MUSIC_EventInputPort_mapLocalIndex (MUSIC_EventInputPort *port,
+					 MUSIC_IndexMap *indices,
+					 MUSIC_EventHandler *handleEvent,
+					 double accLatency,
+					 int maxBuffered);
+
+void MUSIC_MessageOutputPort_map_no_handler (MUSIC_MessageOutputPort *port);
+
+void MUSIC_MessageOutputPort_map (MUSIC_MessageOutputPort *port,
+				  int maxBuffered);
+
+typedef void MUSIC_MessageHandler (double t, void *msg, size_t size);
+
+void MUSIC_MessageInputPort_map (MUSIC_MessageInputPort *port,
+				 MUSIC_MessageHandler *handleMessage,
+				 double accLatency,
+				 int maxBuffered);
+
+/* Index maps */
+
+MUSIC_PermutationIndex *MUSIC_createPermutationIndex (int *indices,
+						      int size);
+
+void MUSIC_destroyPermutationIndex (MUSIC_PermutationIndex *Index);
+
+MUSIC_LinearIndex *MUSIC_createLinearIndex (int baseIndex,
+					    int size);
+
+void MUSIC_destroyLinearIndex (MUSIC_LinearIndex *Index);
+
+/* Exception: The map argument can take any type of index map. */
+
+MUSIC_ArrayData *MUSIC_createArrayData (void *buffer,
+					MPI_Datatype type,
+					void *map);
+
+/* Exception: MUSIC_createLinearArrayData corresponds to
+   c++ MUSIC::ArrayData::ArrayData (..., ..., ..., ...) */
+
+MUSIC_ArrayData *MUSIC_createLinearArrayData (void *buffer,
+					      MPI_Datatype type,
+					      int baseIndex,
+					      int size);
+
+void MUSIC_destroyArrayData (MUSIC_ArrayData *arrayData);
+
+/* Configuration variables */
+
+/* Exceptions: Result is char *
+   Extra maxlen argument prevents buffer overflow.
+   Result is terminated by \0 unless longer than maxlen - 1 */
+
+int MUSIC_configString (MUSIC_Setup *setup,
+			char *name,
+			char *result,
+			size_t maxlen);
+
+int MUSIC_configInt (MUSIC_Setup *setup, char *name, int *result);
+
+int MUSIC_configDouble (MUSIC_Setup *setup, char *name, double *result);
+
+/* Runtime */
+
+typedef struct MUSIC_Runtime MUSIC_Runtime;
+
+MUSIC_Runtime *MUSIC_createRuntime (MUSIC_Setup *setup, double h);
+
+void MUSIC_tick (MUSIC_Runtime *runtime);
+
+double MUSIC_time (MUSIC_Runtime *runtime);
+
+/* Finalization */
+
+void MUSIC_destroyRuntime (MUSIC_Runtime *runtime);
+#endif
+#define MUSIC_C_H
+#endif /* MUSIC_C_H */
diff --git a/src/music.hh b/src/music.hh
new file mode 100644
index 0000000..03853f8
--- /dev/null
+++ b/src/music.hh
@@ -0,0 +1,27 @@
+#ifndef MUSIC_HH
+
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/runtime.hh"
+#include "music/setup.hh"
+#include "music/permutation_index.hh"
+#include "music/array_data.hh"
+
+#define MUSIC_HH
+#endif /* MUSIC_HH */
diff --git a/src/music/.gitignore b/src/music/.gitignore
new file mode 100644
index 0000000..4de2b48
--- /dev/null
+++ b/src/music/.gitignore
@@ -0,0 +1,2 @@
+/music-config.hh
+/version.hh
diff --git a/src/music/BIFO.hh b/src/music/BIFO.hh
new file mode 100644
index 0000000..ffc46b4
--- /dev/null
+++ b/src/music/BIFO.hh
@@ -0,0 +1,69 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_BIFO_HH
+
+#include "music/music-config.hh"
+
+#if MUSIC_USE_MPI
+#include <vector>
+
+#include <music/FIBO.hh>
+
+namespace MUSIC {
+
+  class BIFO {
+  private:
+    std::vector<char> buffer;
+    int elementSize_;
+    int size;			// size of buffer
+
+    // These two variables are used to insert data:
+    
+    int beginning;		// beginning of last block
+    int end;			// end of last block
+
+    // These two variables are used to read data:
+    
+    int current;
+    int top;			// upper bound of valid data
+
+    void grow (int newSize);
+    
+    int maxBlockSize_;
+  public:
+    BIFO () { }
+    void configure (int elementSize, int maxBlockSize);
+
+    // Duplicate the single element in the buffer to a total of nElements
+    // 0 is allowed as argument in which case the buffer is emptied
+    void fill (int nElements);
+    
+    bool isEmpty ();
+    // NOTE: find better return type
+    void* insertBlock ();
+    // size in bytes
+    void trimBlock (int size);
+    void* next ();
+  };
+  
+  
+}
+#endif
+#define MUSIC_BIFO_HH
+#endif
diff --git a/src/music/FIBO.hh b/src/music/FIBO.hh
new file mode 100644
index 0000000..6a87284
--- /dev/null
+++ b/src/music/FIBO.hh
@@ -0,0 +1,53 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_FIBO_HH
+#include "music/music-config.hh"
+#include <vector>
+
+namespace MUSIC {
+
+  class FIBO {
+  private:
+    static const int nInitial = 10;
+    
+    std::vector<char> buffer;
+    int elementSize;
+    int size_;
+    int current;
+
+    void grow (int newSize);
+    
+  public:
+    FIBO () { }
+    FIBO (int elementSize);
+    void configure (int elementSize);
+    bool isEmpty ();
+    // NOTE: find better return type
+    void* insert ();
+    void insert (void* elements, int n_elements);
+    void clear ();
+    void nextBlockNoClear (void*& data, int& size);
+    void nextBlock (void*& data, int& size);
+    unsigned int size () { return size_; } //*fixme* should be n elements
+  };
+  
+  
+}
+#define MUSIC_FIBO_HH
+#endif
diff --git a/src/music/application_graph.hh b/src/music/application_graph.hh
new file mode 100644
index 0000000..4541790
--- /dev/null
+++ b/src/music/application_graph.hh
@@ -0,0 +1,393 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_APPLICATION_GRAPH_HH
+#define MUSIC_APPLICATION_GRAPH_HH
+#include <assert.h>
+#include <vector>
+#include <cstddef>
+namespace MUSIC
+{
+  template<typename NodeData, typename EdgeData>
+    class ANode;
+
+  template<typename NodeData, typename EdgeData>
+    class AEdge
+    {
+      ANode<NodeData, EdgeData> *pre_;
+      ANode<NodeData, EdgeData> *post_;
+      EdgeData *data_;
+    public:
+      AEdge () :
+          pre_ (0), post_ (0), data_ (0)
+      {
+      }
+
+      AEdge (ANode<NodeData, EdgeData> &pre, ANode<NodeData, EdgeData> &post,
+          EdgeData &data) :
+          pre_ (&pre), post_ (&post), data_ (&data)
+      {
+      }
+
+      virtual
+      ~AEdge ()
+      {
+      }
+
+      ANode<NodeData, EdgeData> &
+      post ()
+      {
+        return *post_;
+      }
+
+      ANode<NodeData, EdgeData> &
+      pre ()
+      {
+        return *pre_;
+      }
+
+      EdgeData &
+      data ()
+      {
+        return *data_;
+      }
+    };
+
+  template<typename NodeData, typename EdgeData>
+    class ANode
+    {
+      typedef AEdge<NodeData, EdgeData>* AEdgePtr;
+      AEdgePtr *out_edges_;
+      AEdgePtr *in_edges_;
+
+      int n_out_edges_;
+      int n_in_edges_;
+
+      int c_out_;
+      int c_in_;
+
+      NodeData *data_;
+
+    public:
+      bool in_path;
+      bool visited;
+
+      ANode () :
+          data_ (0)
+      {
+        init (0, 0);
+      }
+
+      ANode (int nOut, int nIn, NodeData &data) :
+          data_ (&data)
+      {
+        init (nOut, nIn);
+      }
+
+      ANode (const ANode<NodeData, EdgeData>& other)
+      {
+        init (other.n_out_edges_, other.n_in_edges_);
+
+        data_ = other.data_;
+        in_path = other.in_path;
+        visited = other.visited;
+        c_out_ = other.c_out_;
+        c_in_ = other.c_in_;
+
+        for (int i = 0; i < c_out_; ++i)
+          out_edges_[i] = other.out_edges_[i];
+        for (int i = 0; i < c_in_; ++i)
+          in_edges_[i] = other.in_edges_[i];
+      }
+
+      virtual
+      ~ANode ()
+      {
+        delete[] out_edges_;
+        delete[] in_edges_;
+      }
+
+      ANode<NodeData, EdgeData>&
+      operator= (const ANode<NodeData, EdgeData>& that)
+      {
+        if (this != &that)
+          {
+            delete[] out_edges_;
+            delete[] in_edges_;
+            init (that.n_out_edges_, that.n_in_edges_);
+
+            data_ = that.data_;
+            in_path = that.in_path;
+            visited = that.visited;
+            c_out_ = that.c_out_;
+            c_in_ = that.c_in_;
+
+            for (int i = 0; i < c_out_; ++i)
+              out_edges_[i] = that.out_edges_[i];
+            for (int i = 0; i < c_in_; ++i)
+              in_edges_[i] = that.in_edges_[i];
+          }
+        return *this;
+      }
+
+      void
+      addEdge (AEdge<NodeData, EdgeData> &edge, bool input = false)
+      {
+        if (input)
+          {
+            assert (c_in_ < n_in_edges_);
+            in_edges_[c_in_++] = &edge;
+          }
+        else
+          {
+            assert (c_out_ < n_out_edges_);
+            out_edges_[c_out_++] = &edge;
+          }
+      }
+
+      void
+      reset ()
+      {
+        in_path = false;
+        visited = false;
+      }
+
+      int
+      nOutEdges ()
+      {
+        return n_out_edges_;
+      }
+
+      int
+      nInEdges ()
+      {
+        return n_in_edges_;
+      }
+
+      AEdge<NodeData, EdgeData> &
+      outEdge (int c)
+      {
+        assert (c < c_out_);
+        return *out_edges_[c];
+      }
+
+      typedef AEdgePtr* edge_iterator;
+
+      edge_iterator
+      begin_o ()
+      {
+        return &out_edges_[0];
+      }
+
+      edge_iterator
+      end_o ()
+      {
+        return &out_edges_[c_out_];
+      }
+
+      edge_iterator
+      begin_i ()
+      {
+        return &in_edges_[0];
+      }
+
+      edge_iterator
+      end_i ()
+      {
+        return &in_edges_[c_in_];
+      }
+
+      NodeData &
+      data ()
+      {
+        assert (data_ != 0);
+        return *data_;
+      }
+
+    private:
+      void
+      init (int nOut, int nIn)
+      {
+        n_out_edges_ = nOut;
+        n_in_edges_ = nIn;
+        out_edges_ = new AEdgePtr[nOut + 1];
+        in_edges_ = new AEdgePtr[nIn + 1];
+        c_in_ = 0;
+        c_out_ = 0;
+        reset ();
+      }
+    };
+
+  template<typename NodeData, typename EdgeData>
+    class AGraph
+    {
+    protected:
+      ANode<NodeData, EdgeData> *nodes_;
+      int c_apps_;
+
+      AEdge<NodeData, EdgeData> *edges_;
+      int c_edges_;
+
+      int color_;
+
+      int n_apps_;
+      int n_edges_;
+
+    public:
+      AGraph (int color, int nApps, int nEdges) :
+          c_apps_ (0), c_edges_ (0), color_ (color), n_apps_ (nApps), n_edges_ (
+              nEdges)
+      {
+        nodes_ = new ANode<NodeData, EdgeData> [nApps + 1];
+        edges_ = new AEdge<NodeData, EdgeData> [nEdges];
+      }
+
+      //AGraph can be a simple array of nodes
+      AGraph (int color, int nApps) :
+          c_apps_ (0), c_edges_ (0), color_ (color), n_apps_ (nApps), n_edges_ (
+              0)
+      {
+        nodes_ = new ANode<NodeData, EdgeData> [nApps + 1];
+        edges_ = NULL;
+      }
+
+      virtual
+      ~AGraph ()
+      {
+        if (edges_ != NULL)
+          delete[] edges_;
+        delete[] nodes_;
+
+      }
+
+      int
+      nNodes ()
+      {
+        return c_apps_;
+      }
+
+      int
+      nEdges ()
+      {
+        return c_edges_;
+      }
+
+      ANode<NodeData, EdgeData> &
+      addNode (ANode<NodeData, EdgeData> node, int color)
+      {
+        assert (color < n_apps_);
+        nodes_[color] = node;
+        assert (c_apps_ < n_apps_);
+        c_apps_++;
+        return nodes_[color];
+      }
+
+      AEdge<NodeData, EdgeData> &
+      addEdge (AEdge<NodeData, EdgeData> edge)
+      {
+        assert (c_edges_ < n_edges_);
+        edges_[c_edges_] = edge;
+        edge.pre ().addEdge (edges_[c_edges_]);
+
+        edge.post ().addEdge (edges_[c_edges_], true);
+
+        c_edges_++;
+        return edges_[c_edges_ - 1];
+      }
+
+      typedef ANode<NodeData, EdgeData> *iterator;
+
+      iterator
+      begin ()
+      {
+        return &nodes_[0];
+      }
+
+      iterator
+      end ()
+      {
+        return &nodes_[c_apps_];
+      }
+
+      ANode<NodeData, EdgeData> &
+      at (int color)
+      {
+        assert (color < c_apps_);
+        return nodes_[color];
+      }
+
+      ANode<NodeData, EdgeData> &
+      local_node ()
+      {
+        assert (color_ < c_apps_);
+        return nodes_[color_];
+      }
+
+      int
+      local_node_color ()
+      {
+        return color_;
+      }
+
+      virtual void
+      reset ()
+      {
+        for (int i = 0; i < c_apps_; ++i)
+          nodes_[i].reset ();
+      }
+
+      void
+      depthFirst (ANode<NodeData, EdgeData> &x,
+          std::vector<AEdge<NodeData, EdgeData> > & path)
+      {
+        if (x.in_path)
+          {
+            handleLoop (x, path); //x.handle_in_path(path);
+            return;
+          }
+
+        // Mark as processed (remove from main loop forest)
+        x.visited = true;
+        x.in_path = true;
+
+        for (int c = 0; c < x.nOutEdges (); ++c)
+          {
+            path.push_back (edge (x, c));
+            depthFirst (edge (x, c).post (), path);
+            path.pop_back ();
+          }
+
+        x.in_path = false;
+      }
+
+    protected:
+      virtual AEdge<NodeData, EdgeData>
+      edge (ANode<NodeData, EdgeData> &x, int c)
+      {
+        return x.outEdge (c);
+      }
+
+      virtual void
+      handleLoop (ANode<NodeData, EdgeData> &x,
+          std::vector<AEdge<NodeData, EdgeData> > & path)
+      {
+      }
+
+    };
+}
+#endif /* MUSIC_APPLICATION_GRAPH_HH */
diff --git a/src/music/application_map.hh b/src/music/application_map.hh
new file mode 100644
index 0000000..447c9de
--- /dev/null
+++ b/src/music/application_map.hh
@@ -0,0 +1,103 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_APPLICATION_MAP_HH
+#include "music/music-config.hh"
+#include <sstream>
+#include <vector>
+#include <map>
+namespace MUSIC {
+
+  class ApplicationInfo
+  {
+    std::string name_;
+    int nProc_;
+    int color_; //used for convenience
+    int leader_;
+
+  public:
+    ApplicationInfo (std::string name, int n, int c) :
+        name_ (name), nProc_ (n), color_ (c), leader_(-1)
+    {
+    }
+
+
+    std::string
+    name ()
+    {
+      return name_;
+    }
+
+
+    int
+    color ()
+    {
+      return color_;
+    }
+
+
+    int
+    nProc ()
+    {
+      return nProc_;
+    }
+
+
+    int
+    leader ()
+    {
+      return leader_;
+    }
+
+
+    void
+    setLeader( int leader)
+    {
+      leader_ = leader;
+    }
+  };
+
+
+  class ApplicationMap : public std::vector<ApplicationInfo>
+  {
+
+  public:
+    ApplicationMap ();
+
+    ApplicationInfo* lookup (std::string appName);
+
+    ApplicationInfo* lookup (int color);
+
+    int nProcesses ();
+
+    void add (std::string name, int n, int c);
+
+    void write (std::ostringstream& out);
+
+    void read (std::istringstream& in);
+
+#if MUSIC_USE_MPI
+    std::map<int, int>
+    assignLeaders (std::string my_app_label);
+#endif
+  };
+
+}
+
+#define MUSIC_APPLICATION_MAP_HH
+#endif
diff --git a/src/music/application_mapper.hh b/src/music/application_mapper.hh
new file mode 100644
index 0000000..4a9023a
--- /dev/null
+++ b/src/music/application_mapper.hh
@@ -0,0 +1,155 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_APPLICATION_MAPPER_HH
+
+#include <istream>
+#include <map>
+
+#include <music/configuration.hh>
+#include "config.h"
+
+namespace rude {
+  class Config;
+}
+
+namespace MUSIC {
+
+
+  class ApplicationSelector
+  {
+
+  protected:
+    bool selected_;
+
+  public:
+    ApplicationSelector (): selected_ (false)
+    {
+    }
+    ;
+    virtual
+    ~ApplicationSelector ()
+    {
+    }
+    ;
+    virtual bool
+    selected (Configuration* config) = 0;
+
+    virtual void
+    reset ()
+    {
+      selected_ = false;
+    }
+  };
+
+
+  class SelectorINO : public ApplicationSelector
+  {
+    long ino_;
+    int my_chunk_;
+    int next_chunk_;
+  public:
+    SelectorINO (long ino, int index) :
+      ApplicationSelector (), ino_ (ino), my_chunk_ (index), next_chunk_(0)
+    {
+    }
+    ;
+    bool
+    selected (Configuration* config);
+
+    void
+    reset ()
+    {
+      ApplicationSelector::reset();
+      next_chunk_ = 0;
+    }
+  };
+
+
+  class SelectorOp : public ApplicationSelector
+  {
+    std::string app_label_;
+  public:
+    SelectorOp (std::string appLabel) :
+        ApplicationSelector (), app_label_ (appLabel)
+    {
+    }
+    ;
+    bool
+    selected (Configuration* config);
+
+  };
+
+
+  class SelectorR : public ApplicationSelector
+  {
+    int rank_;
+    int next_chunk_;
+  public:
+    SelectorR (int rank) :
+        ApplicationSelector (), rank_ (rank), next_chunk_(0)
+    {
+    }
+    ;
+    bool
+    selected (Configuration* config);
+
+  };
+
+
+  class ApplicationMapper
+  {
+
+    rude::Config* cfile_;
+    Configuration* config_;
+    ApplicationMap* applications_;
+    Connectivity* connectivityMap_;
+    ApplicationSelector* app_selector_;
+
+  public:
+    ApplicationMapper (Configuration *config);
+
+    ~ApplicationMapper();
+
+    Configuration* map (std::istream* configFile, int rank);
+
+#if MUSIC_USE_MPI
+    Configuration* map (std::istream* configFile, std::string binary, std::string appLabel);
+#endif
+
+#if HAVE_SYS_STAT_H
+    static long getApplicationINO (const char *path);
+#endif
+
+  private:
+
+    void map(std::istream* configFile);
+
+    void mapApplications ();
+
+    void mapConnectivity (bool leaders);
+
+    void mapSection(int index, Configuration* config);
+
+
+  };
+
+}
+
+#define MUSIC_APPLICATION_MAPPER_HH
+#endif
diff --git a/src/music/array_data.hh b/src/music/array_data.hh
new file mode 100644
index 0000000..e5cf3e3
--- /dev/null
+++ b/src/music/array_data.hh
@@ -0,0 +1,46 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_ARRAY_DATA_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include "music/data_map.hh"
+
+namespace MUSIC {
+
+  /*
+   * This data map is part of the MUSIC API and documented
+   * in section 4.3.9 of the MUSIC manual.
+   */
+
+  class ArrayData : public DataMap {
+    MPI::Datatype type_;
+    IndexMap* indexMap_;
+  public:
+    ArrayData (void* buffer, MPI::Datatype type, IndexMap* map);
+    ArrayData (void* buffer, MPI::Datatype type, int baseIndex, int size);
+    virtual ~ArrayData ();
+    virtual DataMap* copy ();
+    virtual MPI::Datatype type () { return type_; }
+    virtual IndexMap* indexMap () { return indexMap_; }
+  };
+
+}
+#endif
+#define MUSIC_ARRAY_DATA_HH
+#endif
diff --git a/src/music/clock.hh b/src/music/clock.hh
new file mode 100644
index 0000000..df9d435
--- /dev/null
+++ b/src/music/clock.hh
@@ -0,0 +1,84 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_CLOCK_HH
+#include "music/music-config.hh"
+
+namespace MUSIC {
+
+  // ClockState may be negative due to calculations in Synchronizer
+  class ClockState {
+#ifdef MUSIC_HAVE_LONG_LONG
+    long long state;
+#else
+#error 64-bit clocks without long long not yet implemented
+#endif
+  public:
+    ClockState () { }
+    // The following operations should be defined in this header file
+    // so that they can be inlined by the compiler.
+    inline ClockState (const long long s) : state (s) { }
+    ClockState (double t, double tb);
+    inline operator long long () const { return state; }
+    inline ClockState& operator+= (const ClockState& s)
+    {
+      state += s;
+      return *this;
+    }
+    class Serialized;
+    Serialized serialize ();
+    // The serialized representation of a ClockState is guaranteed to
+    // fit in two sequential long values
+    class Serialized {
+      friend Serialized ClockState::serialize ();
+
+    public:
+      signed long upper;
+      unsigned long lower;
+    public:
+      ClockState deserialize ();
+    };
+  };
+  
+  class Clock {
+    ClockState state_;
+    ClockState tickInterval_;
+    double timebase_;
+  public:
+    Clock () { state_ = 0; };
+    Clock (double tb, double h);
+    void configure (double tb, ClockState ti);
+    void reset ();
+    void tick ();
+    void ticks (int n);
+    ClockState tickInterval () { return tickInterval_; }
+    void setTickInterval (ClockState ti) { tickInterval_ = ti; }
+    double timebase () { return timebase_; }
+    double time () const;
+    ClockState integerTime () { return state_; }
+    void set (ClockState state) { state_ = state; }
+    bool operator>= (const Clock& ref) const { return state_ >= ref.state_; }
+    bool operator<= (const Clock& ref) const { return state_ <= ref.state_; }
+    bool operator< (const Clock& ref) const { return state_ < ref.state_; }
+    bool operator!= (const Clock& ref) const {return state_ != ref.state_;}
+    bool operator== (const Clock& ref) const { return state_ == ref.state_; }
+  };
+
+}
+#define MUSIC_CLOCK_HH
+#endif
diff --git a/src/music/collector.hh b/src/music/collector.hh
new file mode 100644
index 0000000..043dbac
--- /dev/null
+++ b/src/music/collector.hh
@@ -0,0 +1,82 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_COLLECTOR_HH
+
+#include "music/music-config.hh"
+
+#if MUSIC_USE_MPI
+// data_map.hh needs to be included first since it includes mpi.h.
+// mpi.h must be included before other header files on BG/L
+#include <music/data_map.hh>
+
+#include <map>
+#include <vector>
+
+#include <music/BIFO.hh>
+#include <music/interval_tree.hh>
+
+namespace MUSIC {
+
+  class Collector {
+  public: //for BG compiler
+    class Interval : public MUSIC::Interval {
+    public:
+      Interval (IndexInterval& interval);
+      bool operator< (const Interval& ref) const
+      { return begin () < ref.begin (); }
+      // length field is stored overlapping the end field so that the
+      // interval information can be "recompiled" for space and time
+      // efficiency
+      int length () const { return end (); }
+      void setLength (int length) { setEnd (length); }
+    };
+private:
+    class IntervalCalculator : public IntervalTree<int, MUSIC::Interval, int>::Action {
+      Interval& interval_;
+      int elementSize_;
+    public:
+      IntervalCalculator (Interval& interval, int elementSize)
+	: interval_ (interval), elementSize_ (elementSize) { };
+      void operator() (int& offset);
+    };
+    
+    typedef std::vector<Interval> Intervals;
+    typedef std::map<BIFO*, Intervals> BufferMap;
+
+    DataMap* dataMap;
+    int maxsize_;
+    BufferMap buffers;
+
+    IntervalTree<int, MUSIC::Interval, int>* buildTree ();
+  public:
+    // caller manages deallocation but guarantees existence
+    /* remedius
+     * second argument int allowedBuffered was changed to int maxsize
+     */
+    void configure (DataMap* dmap, int maxsize);
+    void initialize ();
+    void addRoutingInterval (IndexInterval i, BIFO* b);
+    void collect ();
+    void collect (ContDataT* base);
+  };
+    
+}
+#endif
+#define MUSIC_COLLECTOR_HH
+#endif
diff --git a/src/music/communication.hh b/src/music/communication.hh
new file mode 100644
index 0000000..ae77b34
--- /dev/null
+++ b/src/music/communication.hh
@@ -0,0 +1,41 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_COMMUNICATION_HH
+
+#include "music/data_map.hh"
+
+namespace MUSIC {
+
+  // These are the MPI message tags used by the MUSIC library
+  
+  enum MessageTag {
+    CREATE_INTERCOMM_MSG,
+    TICKINTERVAL_MSG,
+    WIDTH_MSG,
+    SPATIAL_NEGOTIATION_MSG,
+    CONT_MSG,
+    SPIKE_MSG,
+    MESSAGE_MSG,
+    FLUSH_MSG
+  };
+
+}
+
+#define MUSIC_COMMUNICATION_HH
+#endif
diff --git a/src/music/configuration.hh b/src/music/configuration.hh
new file mode 100644
index 0000000..4d3ff00
--- /dev/null
+++ b/src/music/configuration.hh
@@ -0,0 +1,104 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_CONFIGURATION_HH
+
+#include "music/music-config.hh"
+
+#include <string>
+#include <map>
+
+#include "music/application_map.hh"
+#include "music/connectivity.hh"
+
+namespace MUSIC {
+
+  class Configuration {
+  public:
+      static const char* const configEnvVarName;
+      typedef std::map<std::string, std::string> ConfigDict;
+  private:
+
+    std::string app_name_;
+
+    ApplicationMap* applications_;
+    Connectivity* connectivityMap_;
+
+    Configuration* defaultConfig_;
+
+    std::map<std::string, std::string> dict_;
+
+
+  public:
+
+    Configuration ();
+
+#if MUSIC_USE_MPI
+    Configuration (std::string configStr);
+#endif
+
+    ~Configuration ();
+
+    void writeEnv ();
+
+    bool lookup (std::string name);
+
+    bool lookup (std::string name, int* result);
+
+    bool lookup (std::string name, double* result);
+
+    bool lookup(std::string name, std::string* result);
+
+    void insert (std::string name, std::string value);
+
+    const ConfigDict &getDict();
+
+    void setDict(const ConfigDict &dict);
+
+    void resetDict();
+
+    std::string Name();
+
+    void setName( std::string name);
+
+    int Color ();
+
+    int Leader ();
+
+    ApplicationMap* applications ();
+
+    Connectivity* connectivityMap ();
+
+    Configuration* defaultConfig();
+
+  private:
+
+    void init ();
+
+#if MUSIC_USE_MPI
+    void parse (std::string configStr);
+#endif
+
+    void write (std::ostringstream& env, Configuration* mask);
+
+  };
+
+}
+
+#define MUSIC_CONFIGURATION_HH
+#endif
diff --git a/src/music/connection.hh b/src/music/connection.hh
new file mode 100644
index 0000000..8d18f1d
--- /dev/null
+++ b/src/music/connection.hh
@@ -0,0 +1,72 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_CONNECTION_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include <music/connector.hh>
+
+namespace MUSIC {
+  /*
+   * The Connection class carries the extra information needed for
+   * setting up connectors and subconnectors during spatial and
+   * temporal negotiation.  Connection objects are deallocated at the
+   * end of the Runtime constructor.
+   */
+  class Connection {
+  protected:
+    Connector* connector_;
+    int maxBuffered_;
+  public:
+
+    Connection (Connector* connector, int maxBuffered)
+      : connector_ (connector),
+	maxBuffered_ (maxBuffered) { }
+    virtual ~Connection () { } // needed to make base polymorphic (!)
+    Connector* connector () const { return connector_; }
+    //void setConnector (Connector* connector) { connector_ = connector; }
+    int maxBuffered () { return maxBuffered_; }
+  };
+  
+  class OutputConnection : public Connection {
+  private:
+    int elementSize_;
+  public:
+    OutputConnection (Connector* connector,
+		      int maxBuffered,
+		      int elementSize);
+    int elementSize () { return elementSize_; }
+  };
+  
+  class InputConnection : public Connection {
+  private:
+    ClockState accLatency_;
+    bool interpolate_;
+  public:
+    InputConnection (Connector* connector,
+		     int maxBuffered,
+		     ClockState accLatency,
+		     bool interpolate);
+    ClockState accLatency () { return accLatency_; }
+    bool interpolate () { return interpolate_; }
+  };
+
+}
+#endif
+#define MUSIC_CONNECTION_HH
+#endif
diff --git a/src/music/connectivity.hh b/src/music/connectivity.hh
new file mode 100644
index 0000000..ed56111
--- /dev/null
+++ b/src/music/connectivity.hh
@@ -0,0 +1,234 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009, 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_CONNECTIVITY_HH
+
+#include <sstream>
+#include <vector>
+#include <map>
+
+namespace MUSIC {
+/*
+ * Communication Type (<COLLECTIVE, POINTTOPOINT>)
+ * Processing Method (<TREE, TABLE>)
+ */
+  class ConnectorInfo
+  {
+  public:
+
+    enum CommunicationType
+    {
+      COLLECTIVE, POINTTOPOINT
+    };
+
+
+    enum ProcessingMethod
+    {
+      TREE, TABLE
+    };
+
+
+    static int maxPortCode_;
+    std::string recApp_;
+    std::string recPort_;
+    int recCode_;
+    int remoteLeader_;
+    int nProc_;
+    int commType_;
+    int procMethod_;
+
+  public:
+    ConnectorInfo ()
+    {
+    }
+
+
+    ConnectorInfo (std::string recApp, std::string recName, int recCode,
+        int rLeader, int nProc, int commType, int procMethod) :
+        recApp_ (recApp), recPort_ (recName), recCode_ (recCode), remoteLeader_ (
+            rLeader), nProc_ (nProc), commType_ (commType), procMethod_ (
+            procMethod)
+    {
+    }
+
+
+    static void
+    registerPortCode (int portCode);
+
+
+    static int
+    allocPortCode ()
+    {
+      return ++maxPortCode_;
+    }
+
+
+    std::string
+    receiverAppName () const
+    {
+      return recApp_;
+    }
+
+
+    std::string
+    receiverPortName () const
+    {
+      return recPort_;
+    }
+
+
+    int
+    receiverPortCode () const
+    {
+      return recCode_;
+    }
+
+
+    int
+    remoteLeader () const
+    {
+      return remoteLeader_;
+    }
+
+
+    void
+    setRemoteLeader (int leader)
+    {
+      remoteLeader_ = leader;
+    }
+
+
+    // NOTE: nProcesses should have "remote" in name
+    int
+    nProcesses () const
+    {
+      return nProc_;
+    }
+
+
+    int
+    communicationType () const
+    {
+      return commType_;
+    }
+
+
+    int
+    processingMethod () const
+    {
+      return procMethod_;
+    }
+  };
+
+
+  typedef std::vector<ConnectorInfo> PortConnectorInfo;
+
+
+  class ConnectivityInfo
+  {
+
+  public:
+    enum PortDirection
+    {
+      OUTPUT, INPUT
+    };
+
+
+    static const int NO_WIDTH = -1;
+
+  private:
+    std::string portName_;
+    PortDirection dir_;
+    int width_;
+    PortConnectorInfo portConnections_;
+
+  public:
+    ConnectivityInfo (std::string portName, PortDirection dir, int width) :
+        portName_ (portName), dir_ (dir), width_ (width)
+    {
+    }
+
+
+    std::string
+    portName ()
+    {
+      return portName_;
+    }
+
+
+    PortDirection
+    direction ()
+    {
+      return dir_;
+    }
+
+
+    int
+    width ()
+    {
+      return width_;
+    } // NO_WIDTH if no width specified
+
+
+    PortConnectorInfo&
+    connections ()
+    {
+      return portConnections_;
+    }
+
+
+    void  addConnection (std::string recApp, std::string recName, int recCode,
+        int rLeader, int nProc, int commType, int procMethod);
+  };
+
+
+  class Connectivity
+  {
+    std::vector<ConnectivityInfo> connections_;
+    std::map<std::string, int> connectivityMap;
+
+  public:
+    Connectivity ()
+    {
+    }
+
+    static const int NO_CONNECTIVITY = 0;
+
+    void  add (std::string localPort, ConnectivityInfo::PortDirection dir, int width,
+        std::string recApp, std::string recPort, int recPortCode,
+        int remoteLeader, int remoteNProc, int commType, int procMethod);
+
+    ConnectivityInfo* info (std::string portName);
+
+    bool isConnected (std::string portName);
+
+    ConnectivityInfo::PortDirection direction (std::string portName);
+
+    int width (std::string portName);
+
+    PortConnectorInfo connections (std::string portName);
+
+    void write (std::ostringstream& out);
+
+    void read (std::istringstream& in, std::map<int, int> leaders);
+  };
+
+}
+
+#define MUSIC_CONNECTIVITY_HH
+#endif
diff --git a/src/music/connector.hh b/src/music/connector.hh
new file mode 100644
index 0000000..271f521
--- /dev/null
+++ b/src/music/connector.hh
@@ -0,0 +1,628 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009, 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_CONNECTOR_HH
+
+#include "music/music-config.hh"
+
+#if MUSIC_USE_MPI
+
+#include <vector>
+#include <string>
+
+//#include <music/synchronizer.hh>
+#include <music/FIBO.hh>
+#include <music/event.hh>
+#include <music/spatial.hh>
+#include <music/connectivity.hh>
+#include <music/sampler.hh>
+#include <music/collector.hh>
+#include <music/distributor.hh>
+#include <music/event_routing_map.hh>
+#include <music/clock.hh>
+#include <music/subconnector.hh>
+
+namespace MUSIC {
+  /* remedius
+   * New type of Connector was introduced: CollectiveConnector.
+   * So that Connector class hierarchy undergoes the following changes:
+   * the common functionality for OutputConnector and InputConnector classes was moved to the base Connector class.
+   */
+  // The Connector is responsible for one side of the communication
+  // between the ports of a port pair.  An output port can have
+  // multiple connectors while an input port only has one.  The method
+  // connector::connect () creates one subconnector for each MPI
+  // process we will communicate with on the remote side.
+
+  /* remedius
+   */
+
+  class MultiBuffer;
+
+  class Connector
+  {
+  private:
+    static std::map<unsigned int, Connector*> flagMap_;
+    static unsigned int nextFlag_;
+    static unsigned int nextProxyFlag_;
+  protected:
+    ConnectorInfo info;
+    IndexMap* indices_;
+    Index::Type type_;
+    MPI::Intracomm comm;
+    MPI::Intercomm intercomm;
+    std::vector<Subconnector*> rsubconn;
+    ClockState latency_;
+    // interpolate rather than picking value closest in time
+    bool interpolate_;
+    int width_;
+    int maxLocalWidth_;
+    unsigned int idFlag_;
+    bool finalized_;
+
+    Connector () { };
+    Connector (ConnectorInfo info_,
+	       IndexMap* indices,
+	       Index::Type type,
+	       MPI::Intracomm c);
+    Connector (ConnectorInfo info_,
+	       IndexMap* indices,
+	       Index::Type type,
+	       MPI::Intracomm c,
+	       MPI::Intercomm ic);
+
+    static unsigned int makeFlag (Connector* connector)
+    {
+      unsigned int flag = nextFlag_;
+      nextFlag_ <<= 1;
+
+      flagMap_[flag] = connector;
+
+      return flag;
+    }
+
+    static unsigned int makeProxyFlag ()
+    {
+      unsigned int flag = nextProxyFlag_;
+      nextProxyFlag_ <<= 1;
+      return flag;
+    }
+
+  public:
+
+    static Connector* connectorFromIdFlag (unsigned int flag)
+    {
+      return flagMap_[flag];
+    }
+
+    static unsigned int idRange () { return nextFlag_; }
+
+    static unsigned int proxyIdRange () { return nextProxyFlag_; }
+
+    void report ()
+    {
+      for (std::vector<Subconnector*>::iterator subconnector = rsubconn.begin ();
+	   subconnector != rsubconn.end ();
+	   ++subconnector)
+	(*subconnector)->report ();
+    }
+    virtual ~Connector ()
+    {
+      for (std::vector<Subconnector*>::iterator subconnector = rsubconn.begin ();
+	   subconnector != rsubconn.end ();
+	   ++subconnector)
+	delete *subconnector;
+    }
+    virtual void specialize (Clock& localTime) { }
+
+    unsigned int idFlag () const { return idFlag_; }
+    bool needsMultiCommunication () const { return idFlag (); }
+    virtual bool isProxy () const { return false; }
+    virtual bool isInput () const { return false; }
+    std::string receiverAppName () const { return info.receiverAppName (); }
+    std::string receiverPortName () const { return info.receiverPortName (); }
+    int receiverPortCode () const { return info.receiverPortCode (); }
+    int remoteLeader () const { return info.remoteLeader (); }
+    int remoteNProcs () const { return info.nProcesses (); }
+    int width(){return width_;}
+    int maxLocalWidth () { return maxLocalWidth_; }
+    bool isLeader ();
+    virtual void setInterpolate(bool val){interpolate_ =  val;}
+    virtual void setLatency( ClockState latency){ latency_ = latency;}
+    // virtual Synchronizer* synchronizer () = 0;
+    virtual void createIntercomm ();
+    virtual void freeIntercomm ();
+
+    /* remedius
+     * since there can be different types of Subconnectors,
+     * Instead of adding new type of Subconnector,
+     * function parameters' were changed to one parameter without specifying the type of Subconnector and
+     * the common functionality for InputConnector::spatialNegotiation and OutputConnector::spatialNegotiation
+     * was coded in this base Connector::spatialNegotiation() method.
+     * Returns SubconnectorType.
+     */
+    virtual void spatialNegotiation ();
+    /* remedius
+     *  sorts its vector of subconnectors according to its world rank.
+     */
+    virtual void initialize ();
+
+    /* remedius
+     * finalize method iterates its subconnectors and calls accordring flush method
+     */
+    virtual void finalize ();
+
+    virtual bool isFinalized () { return finalized_; }
+
+    /* remedius
+     * tick method iterates its subconnectors and call according function to perform communication;
+     * requestCommunication method argument was removed since there is no need anymore to check for next communication.
+     * Communication is scheduled by separate Scheduler objects that Runtime object contains.
+     */
+    virtual void tick ();
+    /* remedius
+     * In order to carry out the base functionality to the spatialNegotiation() method
+     * the two following common virtual methods were added so that
+     * all successors of this class had to override abstract makeSubconnector method
+     * instead of implementing it's own make^SpecificType^Subconnector() method.
+     */
+  protected:
+    virtual void addRoutingInterval (IndexInterval i, Subconnector* s){};
+    virtual Subconnector* makeSubconnector (int remoteRank){return NULL;};
+
+    virtual void spatialNegotiation (SpatialNegotiator *spatialNegotiator_);
+    virtual SpatialNegotiator *createSpatialNegotiator(){return NULL;};
+  };
+
+
+  class ProxyConnector : virtual public Connector {
+    int senderNode_;
+    int senderLeader_;
+    int senderNProcs_;
+    int receiverNode_;
+    int receiverLeader_;
+    int receiverNProcs_;
+    int currentNode_;
+  public:
+    ProxyConnector (int senderNode, int senderLeader, int senderNProcs,
+		    int receiverNode, int receiverLeader, int receiverNProcs)
+      : senderLeader_ (senderLeader), senderNProcs_ (senderNProcs),
+	receiverLeader_ (receiverLeader), receiverNProcs_ (receiverNProcs)
+    { idFlag_ = makeProxyFlag (); }
+    ProxyConnector (){idFlag_ =0;}
+    bool isProxy () const { return true; }
+    void tick () { }
+    void setNode (int nodeId)
+    {
+      currentNode_ = nodeId;
+      //*fixme*
+      if (isInput ())
+	info.setRemoteLeader (senderLeader ());
+      else
+	info.setRemoteLeader (receiverLeader ());
+    }
+    bool isInput () { return receiverNode_ == currentNode_; }
+    int senderLeader () const { return senderLeader_; }
+    int senderNProcs () const { return senderNProcs_; }
+    int receiverLeader () const { return receiverLeader_; }
+    int receiverNProcs () const { return receiverNProcs_; }
+  };
+
+
+  class PostCommunicationConnector : virtual public Connector {
+  public:
+    virtual void postCommunication () = 0;
+  };
+  class PreCommunicationConnector : virtual public Connector {
+  public:
+    virtual void preCommunication () = 0;
+  };
+  class OutputConnector : virtual public Connector {
+  public:
+#if MUSIC_ISENDWAITALL
+   virtual void tick ();
+#endif // MUSIC_ISENDWAITALL
+  protected:
+    OutputConnector(){};
+    SpatialNegotiator *createSpatialNegotiator();
+  };
+
+  class InputConnector : virtual public Connector {
+/*
+  public:
+#ifdef MUSIC_ANYSOURCE
+	  virtual void tick ();
+#endif // MUSIC_ANYSOURCE
+*/
+  protected:
+    InputConnector(){};
+    bool isInput () const { return true; }
+    SpatialNegotiator *createSpatialNegotiator();
+  };
+
+
+  class ContConnector : virtual public Connector {
+  protected:
+    Sampler& sampler_;
+    MPI::Datatype  data_type_;
+
+    Clock *localTime_;
+    Clock remoteTime_;
+
+  public:
+    ContConnector (Sampler& sampler, MPI::Datatype type)
+      : sampler_ (sampler),  data_type_ (type),localTime_(NULL) { }
+    ClockState remoteTickInterval (ClockState tickInterval);
+    MPI::Datatype getDataType(){return  data_type_;}
+    virtual void initialize ();
+  protected:
+    virtual void initialCommunication()=0;
+    friend class SpecializedContConnector;
+  };
+
+  class ContOutputConnector : public ContConnector, public OutputConnector, public PreCommunicationConnector  {
+  protected:
+    Distributor distributor_;
+    PreCommunicationConnector* connector; //specialized connector
+    ContOutputConnector(Sampler& sampler, MPI::Datatype type);
+  public:
+    ContOutputConnector (ConnectorInfo connInfo,
+			 IndexMap* indices,
+			 Index::Type type,
+			 MPI::Intracomm comm,
+			 Sampler& sampler,
+			 MPI::Datatype data_type);
+    ~ContOutputConnector();
+    //MUSIC_ISENDWAITALL is not supported temporarily for cont. ports
+#if MUSIC_ISENDWAITALL
+    void tick (){Connector::tick();};
+#endif
+    void specialize (Clock& localTime);
+    void preCommunication () {connector->preCommunication(); }
+    void initialize (){connector->initialize();ContConnector::initialize();};
+  protected:
+    void addRoutingInterval (IndexInterval i, Subconnector* osubconn);
+    Subconnector* makeSubconnector (int remoteRank);
+    void initialCommunication();
+    friend class SpecializedContOuputConnector;
+  };
+
+  class ContInputConnector : public ContConnector,  public InputConnector,  public PostCommunicationConnector {
+
+  protected:
+    Collector collector_;
+    double delay_;
+    PostCommunicationConnector* connector;
+    bool divisibleDelay (Clock& localTime);
+    ContInputConnector(Sampler& sampler,MPI::Datatype type,	double delay);
+  public:
+    ContInputConnector (ConnectorInfo connInfo,
+			IndexMap* indices,
+			Index::Type type,
+			MPI::Intracomm comm,
+			Sampler& sampler,
+			MPI::Datatype data_type,
+			double delay);
+    ~ContInputConnector();
+    void specialize (Clock& localTime);
+    void postCommunication () {connector->postCommunication(); }
+    void initialize (){connector->initialize();ContConnector::initialize();};
+    //MUSIC_ANYSOURCE is not supported temporarily for cont. ports
+//#ifdef MUSIC_ANYSOURCE
+//  virtual void tick {Connector::tick();};
+//#endif // MUSIC_ANYSOURCE
+  protected:
+    void addRoutingInterval (IndexInterval i, Subconnector* isubconn);
+    void initialCommunication();
+    Subconnector* makeSubconnector (int remoteRank);
+  private:
+    int initialBufferedTicks();
+    friend class SpecializedContInputConnector;
+  };
+
+
+  class EventOutputConnector : public OutputConnector{
+  private:
+    EventRoutingMap<FIBO*>* routingMap_;
+  public:
+    EventOutputConnector (ConnectorInfo connInfo,
+			  IndexMap* indices,
+			  Index::Type type,
+			  MPI::Intracomm comm,
+			  EventRoutingMap<FIBO*>* routingMap): Connector(connInfo, indices, type ,comm),
+							       routingMap_(routingMap){
+    };
+    ~EventOutputConnector(){}
+
+  protected:
+    EventOutputConnector():routingMap_(NULL){};
+    EventOutputConnector(EventRoutingMap<FIBO*>* routingMap): routingMap_(routingMap){};
+    Subconnector* makeSubconnector (int remoteRank);
+    void addRoutingInterval (IndexInterval i, Subconnector* subconn);
+  };
+  class EventInputConnector : public InputConnector {
+  protected:
+    //	EventRoutingMap<EventHandlerGlobalIndex*>* routingMap_;
+    EventHandlerPtr handleEvent_;
+    std::map<int,EventInputSubconnectorGlobal*> rRank2Subconnector;
+    int flushes;
+  public:
+
+    EventInputConnector (ConnectorInfo connInfo,
+			 IndexMap* indices,
+			 Index::Type type,
+			 MPI::Intracomm comm,
+			 EventHandlerPtr handleEvent):Connector(connInfo, indices, type ,comm),
+						      handleEvent_(handleEvent),flushes(0){};
+    ~EventInputConnector(){}
+    //probably should be moved to InputConnector later
+#if MUSIC_ANYSOURCE
+  void tick ();
+#endif // MUSIC_ANYSOURCE
+  protected:
+    EventInputConnector(){};
+    EventInputConnector (EventHandlerPtr handleEvent): handleEvent_(handleEvent){};
+    Subconnector* makeSubconnector (int remoteRank);
+    /* remedius
+     * original version of the following function does nothing,
+     * however this function could perform inserting interval to the routingMap_ as well,
+     * that is currently done in CollectiveConnector::addRoutingInterval.
+     * This could give an opportunity to have different event handlers for different ranges of indexes as in collective algorithm.
+     * Do we need this? If not, then it's better to leave as it is.
+     */
+    void addRoutingInterval (IndexInterval i, Subconnector* subconn);
+  };
+
+
+  class MessageOutputConnector : public OutputConnector,
+				 public PostCommunicationConnector {
+  private:
+    //   OutputSynchronizer synch;
+    FIBO buffer;
+    bool bufferAdded;
+    std::vector<FIBO*>& buffers_;
+    void send ();
+  public:
+    MessageOutputConnector (ConnectorInfo connInfo,
+			    IndexMap* indices,
+			    Index::Type type,
+			    MPI::Intracomm comm,
+			    std::vector<FIBO*>& buffers);
+
+    void postCommunication ();
+    //MUSIC_ISENDWAITALL is not supported temporarily for message ports
+#if MUSIC_ISENDWAITALL
+    void tick (){Connector::tick();};
+#endif
+  protected:
+    void addRoutingInterval (IndexInterval i, Subconnector* subconn);
+    Subconnector* makeSubconnector (int remoteRank);
+    SpatialNegotiator *createSpatialNegotiator() {return OutputConnector::createSpatialNegotiator();};
+  };
+
+  class MessageInputConnector : public InputConnector {
+
+  private:
+    MessageHandler* handleMessage_;
+  public:
+    MessageInputConnector (ConnectorInfo connInfo,
+			   IndexMap* indices,
+			   Index::Type type,
+			   MessageHandler* handleMessage,
+			   MPI::Intracomm comm);
+    //MUSIC_ANYSOURCE is not supported temporarily for message ports
+/*
+#ifdef MUSIC_ANYSOURCE
+  virtual void tick {Connector::tick();};
+#endif // MUSIC_ANYSOURCE
+*/
+  protected:
+    Subconnector* makeSubconnector (int remoteRank);
+  };
+  /* remedius
+   * New class hierarchy CollectiveConnector was introduced in order to create CollectiveSubconnector object.
+   * The difference between InputConnector, OutputConnector instances and  CollectiveConnector is
+   * the latest creates one CollectiveSubconnector responsible for the collective communication
+   * among all ranks on the output and input sides, while InputConnector and OutputConnector
+   * instances are responsible for creating as much Subconnectors as necessary for each point2point connectivity
+   * for output and input sides.
+   */
+
+  class CollectiveConnector: virtual public Connector {
+    bool high_;
+  protected:
+    MPI::Intracomm intracomm_;
+    Subconnector* subconnector_;
+  public:
+    CollectiveConnector (bool high);
+    virtual Subconnector* makeSubconnector (void *param) = 0;
+    void createIntercomm ();
+    void freeIntercomm ();
+    Subconnector* subconnector () { return subconnector_; }
+  };
+
+  class ContCollectiveConnector: public CollectiveConnector {
+    MPI::Datatype data_type;
+  protected:
+    ContCollectiveConnector( MPI::Datatype type, bool high);
+    Subconnector* makeSubconnector (void *param);
+  };
+
+  class EventCollectiveConnector: public CollectiveConnector {
+  protected:
+    EventRouter *router_; //is used for processing received information
+    EventCollectiveConnector( bool high);
+  public:
+    void createIntercomm () { Connector::createIntercomm (); }
+    void freeIntercomm () { Connector::freeIntercomm (); }
+  };
+
+  class EventInputCollectiveConnector:  public EventInputConnector, public EventCollectiveConnector {
+    EventRoutingMap<EventHandlerPtr*>* routingMap_input; //is used to fill the information for the receiver
+  public:
+    EventInputCollectiveConnector(ConnectorInfo connInfo,
+				  IndexMap* indices,
+				  Index::Type type,
+				  MPI::Intracomm comm,
+				  EventHandlerPtr handleEvent);
+    ~EventInputCollectiveConnector();
+#if MUSIC_ANYSOURCE
+  void tick() { Connector::tick();};
+#endif // MUSIC_ANYSOURCE
+  protected:
+    void spatialNegotiation ( SpatialNegotiator* spatialNegotiator_);
+    void addRoutingInterval(IndexInterval i, Subconnector* subconn);
+    Subconnector* makeSubconnector (void *param);
+    void finalize () { };
+    bool isFinalized () { return subconnector ()->isFlushed (); }
+  };
+
+  class DirectRouter;
+
+  class EventOutputCollectiveConnector:  public EventOutputConnector,public EventCollectiveConnector{
+    DirectRouter* directRouter_;
+  public:
+    EventOutputCollectiveConnector(ConnectorInfo connInfo,
+				   IndexMap* indices,
+				   Index::Type type,
+				   MPI::Intracomm comm,
+				   DirectRouter* router);
+    ~EventOutputCollectiveConnector();
+#if MUSIC_ISENDWAITALL
+    void tick (){Connector::tick();};
+#endif //MUSIC_ISENDWAITALL
+  protected:
+    void spatialNegotiation ( SpatialNegotiator* spatialNegotiator_);
+    Subconnector* makeSubconnector (void *param);
+  };
+
+  class ContInputCollectiveConnector: public ContInputConnector, public ContCollectiveConnector
+  {
+  public:
+    ContInputCollectiveConnector(ConnectorInfo connInfo,
+				 IndexMap* indices,
+				 Index::Type type,
+				 MPI::Intracomm comm,
+				 Sampler& sampler,
+				 MPI::Datatype data_type,
+				 double delay);
+#if MUSIC_ANYSOURCE
+  virtual void tick() {Connector::tick();};
+#endif // MUSIC_ANYSOURCE
+  protected:
+    void spatialNegotiation ( SpatialNegotiator* spatialNegotiator_);
+  private:
+    void receiveRemoteCommRankID(std::map<int,int> &remoteToCollectiveRankMap);
+  };
+
+  class ContOutputCollectiveConnector:  public ContOutputConnector, public ContCollectiveConnector
+  {
+  public:
+    ContOutputCollectiveConnector(ConnectorInfo connInfo,
+				  IndexMap* indices,
+				  Index::Type type,
+				  MPI::Intracomm comm,
+				  Sampler& sampler,
+				  MPI::Datatype data_type);
+#if MUSIC_ISENDWAITALL
+    void tick (){Connector::tick();};
+#endif
+  protected:
+    void spatialNegotiation ( SpatialNegotiator* spatialNegotiator_);
+  private:
+    void sendLocalCommRankID();
+  };
+  class SpecializedContConnector{
+  protected:
+    Sampler& sampler_;
+    Clock *localTime_;
+    Clock &remoteTime_;
+    ClockState &latency;
+    bool &interp;
+    SpecializedContConnector(ContConnector *conn):
+    sampler_ ( conn->sampler_),
+    localTime_(conn->localTime_),
+    remoteTime_(conn->remoteTime_),
+    latency( conn->latency_),
+    interp( conn->interpolate_){};
+  };
+  class SpecializedContOuputConnector:public SpecializedContConnector{
+  protected:
+    Distributor &distributor_;
+    SpecializedContOuputConnector( ContOutputConnector *conn):
+    SpecializedContConnector(conn),
+    distributor_(conn->distributor_){ }
+  };
+  class SpecializedContInputConnector:public SpecializedContConnector{
+  protected:
+    Collector &collector_;
+    SpecializedContInputConnector( ContInputConnector *conn):
+    SpecializedContConnector(conn),
+    collector_(conn->collector_){}
+  };
+  class PlainContOutputConnector : public PreCommunicationConnector, public SpecializedContOuputConnector {
+  protected:
+    PlainContOutputConnector ( ContOutputConnector *conn):SpecializedContOuputConnector(conn){};
+  public:
+    void initialize ();
+    void preCommunication();
+  private:
+    bool sample();
+    friend class ContOutputConnector;
+
+  };
+
+  class InterpolatingContOutputConnector :  public PreCommunicationConnector, public SpecializedContOuputConnector
+  {
+  protected:
+    InterpolatingContOutputConnector (ContOutputConnector *conn):SpecializedContOuputConnector(conn){};
+  public:
+    void initialize ();
+    void preCommunication();
+  private:
+    bool interpolate();
+    bool sample();
+    double interpolationCoefficient();
+    friend class ContOutputConnector;
+
+  };
+  class PlainContInputConnector : public PostCommunicationConnector, public SpecializedContInputConnector {
+  protected:
+    PlainContInputConnector (ContInputConnector *conn):SpecializedContInputConnector(conn){};
+  public:
+    void initialize ();
+    void postCommunication ();
+    friend class ContInputConnector;
+  };
+
+  class InterpolatingContInputConnector : public PostCommunicationConnector, public SpecializedContInputConnector  {
+    bool first_;
+  protected:
+    InterpolatingContInputConnector (ContInputConnector *conn):SpecializedContInputConnector(conn){};
+  public:
+    void initialize ();
+    void postCommunication ();
+  private:
+    bool sample();
+    double interpolationCoefficient();
+    friend class ContInputConnector;
+  };
+}
+#endif
+#define MUSIC_CONNECTOR_HH
+#endif
diff --git a/src/music/cont_data.hh b/src/music/cont_data.hh
new file mode 100644
index 0000000..6c45cb6
--- /dev/null
+++ b/src/music/cont_data.hh
@@ -0,0 +1,35 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_CONT_DATA_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include "music/data_map.hh"
+
+namespace MUSIC {
+
+  class ContData : public DataMap {
+  public:
+    ContData (IndexMap* map);
+    ContData (int baseIndex, int size);
+  };
+
+}
+#endif
+#define MUSIC_CONT_DATA_HH
+#endif
diff --git a/src/music/data_map.hh b/src/music/data_map.hh
new file mode 100644
index 0000000..fc8e0f4
--- /dev/null
+++ b/src/music/data_map.hh
@@ -0,0 +1,53 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_DATA_MAP_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include <mpi.h>
+
+#include "music/index_map.hh"
+
+namespace MUSIC {
+
+  typedef char ContDataT;
+
+  /*
+   * The current interface should maybe be changed so that data maps
+   * are read as a set of pairs of intervals and addresses similar to
+   * the EventRoutingData data structure.  This allows for easier
+   * extension to more generic types of data maps.
+   */
+
+  class DataMap {
+  protected:
+    void* base_;
+  public:
+    DataMap () { };
+    virtual ~DataMap () { };
+    DataMap (void* base) : base_ (base) { };
+    virtual DataMap* copy () = 0;
+    void* base () const { return base_; }
+    virtual MPI::Datatype type () = 0;
+    virtual IndexMap* indexMap () = 0;
+  };
+
+}
+#endif
+#define MUSIC_DATA_MAP_HH
+#endif
diff --git a/src/music/debug.hh b/src/music/debug.hh
new file mode 100644
index 0000000..717c0e7
--- /dev/null
+++ b/src/music/debug.hh
@@ -0,0 +1,76 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef MUSIC_DEBUG_HH
+
+#ifdef MUSIC_DEBUG
+
+#include <iostream>
+
+#define MUSIC_LOG(X) (std::cerr << X << std::endl << std::flush)
+#if MUSIC_USE_MPI
+#define MUSIC_LOGN(N, X) \
+  { if (MPI::COMM_WORLD.Get_rank () == N) MUSIC_LOG (X); }
+
+#define MUSIC_LOG0(X) MUSIC_LOGN (0, X)
+
+#define MUSIC_LOGR(X)					\
+  {							\
+    std::cerr << MPI::COMM_WORLD.Get_rank () << ": "	\
+              << X << std::endl << std::flush;		\
+  }
+
+#define MUSIC_LOGRE(X)					\
+  {							\
+    int _r = MPI::COMM_WORLD.Get_rank ();		\
+    char* _e = getenv ("MUSIC_DEBUG_RANK");		\
+    if (_e != NULL && atoi (_e) == _r)			\
+      {							\
+	std::cerr << _r << ": "				\
+		  << X << std::endl << std::flush;	\
+      }							\
+  }
+
+#define MUSIC_LOGBR(C, X)			\
+  {						\
+    int _r = (C).Get_rank ();			\
+    int _n = (C).Get_size ();			\
+    for (int _i = 0; _i < _n; ++_i)		\
+      {						\
+	(C).Barrier ();				\
+	if (_i == _r)				\
+	  MUSIC_LOGR (X);			\
+      }						\
+  }
+
+#define MUSIC_LOGX(X)
+#endif
+
+#else
+
+#define MUSIC_LOG(X)
+#define MUSIC_LOGN(N, X)
+#define MUSIC_LOG0(X)
+#define MUSIC_LOGR(X)
+#define MUSIC_LOGRE(X)
+#define MUSIC_LOGBR(C, X)
+#define MUSIC_LOGX(X)
+
+#endif
+
+#define MUSIC_DEBUG_HH
+#endif
diff --git a/src/music/distributor.hh b/src/music/distributor.hh
new file mode 100644
index 0000000..39beb83
--- /dev/null
+++ b/src/music/distributor.hh
@@ -0,0 +1,76 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_DISTRIBUTOR_HH
+
+#include "music/music-config.hh"
+
+#if MUSIC_USE_MPI
+// data_map.hh needs to be included first since it includes mpi.h.
+// mpi.h must be included before other header files on BG/L
+#include <music/data_map.hh>
+
+#include <map>
+#include <vector>
+
+#include <music/FIBO.hh>
+#include <music/interval_tree.hh>
+
+namespace MUSIC {
+
+  class Distributor {
+  public: //for BG compiler
+    class Interval : public MUSIC::Interval {
+    public:
+      Interval (IndexInterval& interval);
+      bool operator< (const Interval& ref) const
+      { return begin () < ref.begin (); }
+      // length field is stored overlapping the end field so that the
+      // interval information can be "recompiled" for space and time
+      // efficiency
+      int length () const { return end (); }
+      void setLength (int length) { setEnd (length); }
+    };
+private:
+    class IntervalCalculator : public IntervalTree<int, MUSIC::Interval, int>::Action {
+      Interval& interval_;
+      int elementSize_;
+    public:
+      IntervalCalculator (Interval& interval, int elementSize): interval_ (interval), elementSize_ (elementSize) { };
+      void operator() (int& offset);
+    };
+    
+    typedef std::vector<Interval> Intervals;
+    typedef std::map<FIBO*, Intervals> BufferMap;
+
+    DataMap* dataMap;
+    BufferMap buffers;
+
+    IntervalTree<int, MUSIC::Interval, int>* buildTree ();
+  public:
+    // caller manages deallocation but guarantees existence
+    void configure (DataMap* dmap);
+    void initialize ();
+    void addRoutingInterval (IndexInterval i, FIBO* b);
+    void distribute ();
+  };
+    
+}
+#endif
+#define MUSIC_DISTRIBUTOR_HH
+#endif
diff --git a/src/music/error.hh b/src/music/error.hh
new file mode 100644
index 0000000..7bd0184
--- /dev/null
+++ b/src/music/error.hh
@@ -0,0 +1,41 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_ERROR_HH
+
+#include <sstream>
+#include <string>
+
+namespace MUSIC {
+
+  void error ();
+  void hang ();
+  void error (std::string msg);
+  void error (std::ostringstream& ostr);
+  void error0 (std::string msg);
+  void errorRank (std::string msg);
+  void checkOnce (bool& flag, std::string msg);
+  void checkInstantiatedOnce (bool& flag, std::string className);
+  void checkCalledOnce (bool& isCalled,
+			std::string funcName,
+			std::string suffix);
+  
+}
+
+#define MUSIC_ERROR_HH
+#endif
diff --git a/src/music/event.hh b/src/music/event.hh
new file mode 100644
index 0000000..4c8dde3
--- /dev/null
+++ b/src/music/event.hh
@@ -0,0 +1,97 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_EVENT_HH
+#include <music/index_map.hh>
+
+namespace MUSIC {
+
+  class Event {
+  public:
+    double t;
+    int id;
+    Event (double t_, int id_) : t (t_), id (id_) { }
+    bool operator< (const Event& other) const { return t < other.t; }
+  };
+
+
+  class EventHandlerGlobalIndex {
+  public:
+    virtual void operator () (double t, GlobalIndex id) = 0;
+  };
+  
+  class EventHandlerGlobalIndexDummy : public EventHandlerGlobalIndex {
+  public:
+    virtual void operator () (double t, GlobalIndex id) { };
+  };
+  
+  class EventHandlerGlobalIndexProxy
+    : public EventHandlerGlobalIndex {
+    void (*eventHandler) (double t, int id);
+  public:
+    EventHandlerGlobalIndexProxy () { }
+    EventHandlerGlobalIndexProxy (void (*eh) (double t, int id))
+      : eventHandler (eh) { }
+    void operator () (double t, GlobalIndex id)
+    {
+      eventHandler (t, id);
+    }
+  };
+  
+  class EventHandlerLocalIndex {
+  public:
+    virtual void operator () (double t, LocalIndex id) = 0;
+  };
+
+  class EventHandlerLocalIndexDummy : public EventHandlerLocalIndex {
+  public:
+    virtual void operator () (double t, LocalIndex id) { };
+  };
+
+  class EventHandlerLocalIndexProxy
+    : public EventHandlerLocalIndex {
+    void (*eventHandler) (double t, int id);
+  public:
+    EventHandlerLocalIndexProxy () { }
+    EventHandlerLocalIndexProxy (void (*eh) (double t, int id))
+      : eventHandler (eh) { }
+    void operator () (double t, LocalIndex id)
+    {
+      eventHandler (t, id);
+    }
+  };
+
+  class EventHandlerPtr {
+    union {
+      EventHandlerGlobalIndex* global;
+      EventHandlerLocalIndex* local;
+    } ptr;
+    Index::Type type_;
+  public:
+    EventHandlerPtr () { }
+    EventHandlerPtr (EventHandlerGlobalIndex* p):type_(Index::GLOBAL) { ptr.global = p; }
+    EventHandlerPtr (EventHandlerLocalIndex* p):type_(Index::LOCAL) { ptr.local = p; }
+    typedef EventHandlerGlobalIndex* EventHandlerGlobalIndexPtr;
+    operator EventHandlerGlobalIndex* () { return ptr.global; }
+    operator EventHandlerLocalIndex* () { return ptr.local; }
+    Index::Type getType(){return type_;}
+  };
+  
+}
+#define MUSIC_EVENT_HH
+#endif
diff --git a/src/music/event_router.hh b/src/music/event_router.hh
new file mode 100644
index 0000000..1929c8a
--- /dev/null
+++ b/src/music/event_router.hh
@@ -0,0 +1,253 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_EVENT_ROUTER_HH
+#include <map>
+#include <vector>
+
+#include <music/music-config.hh>
+#include <music/FIBO.hh>
+#include <music/index_map.hh>
+#include <music/event.hh>
+
+#include <music/interval_tree.hh>
+
+#define MUSIC_ITABLE_FLAVOR MUSIC_SCATTERED
+//#define MUSIC_ITABLE_COMPRESSED
+#include <music/interval_table.hh>
+
+namespace MUSIC {
+  /* remedius
+   * Since the router can act as on the output (point-to-point communication)
+   * as well as on the input (collective communication) sides and
+   * pre-/post-processing approaches are different
+   * (in one case it's insertion to the buffer <FIBO>,
+   * in another case it's calling appropriate handler <EventHandlerGlobalIndex>),
+   * two more successors for EventRoutingData were created:
+   * InputRoutingData and OutputRoutingData.
+   */
+
+  class EventRoutingData {
+    int offset_;
+  public:
+    EventRoutingData () { }
+    EventRoutingData (const IndexInterval &i) : offset_ (i.local ()) { }
+    EventRoutingData (const EventRoutingData& e) : offset_ (e.offset_) { }
+    ~EventRoutingData(){};
+    int offset () const { return offset_; }
+  };
+
+  template<class EventHandler>
+  class InputRoutingData : public EventRoutingData {
+    EventHandler* eventHandler_;
+  public:
+    InputRoutingData (const IndexInterval &i, EventHandlerPtr* h)
+      : EventRoutingData (i), eventHandler_ (*h) { }
+    InputRoutingData () : eventHandler_ (NULL) { }
+    void process (double t, int id) { (*eventHandler_) (t, id); }
+  };
+
+  class OutputRoutingData : public EventRoutingData {
+    FIBO* buffer_;
+  public:
+    OutputRoutingData (const IndexInterval &i, FIBO* b);
+    OutputRoutingData () {}
+    void process (double t, int id);
+  };
+
+  class DirectRouter; //Remove this later
+
+  /* remedius
+   * We've decided to try different methods for pre-/post-processing the data:
+   * using tree algorithm and using table.
+   * Hence to this two EventRouter successors were created:
+   * TableProcessingRouter and TreeProcessingRouter.
+   * Currently TableProcessingRouter can handle only GlobalIndex processing.
+   */
+  class EventRouter {
+  public:
+    virtual ~EventRouter() {};
+    virtual void buildTable () {};
+    /* remedius
+     * insertEvent method was renamed to processEvent method,
+     * since we've introduced event processing on the input side as well.
+     */
+    virtual void insertRoutingData (Interval& i, OutputRoutingData& data) {}
+    virtual void insertRoutingData (Interval& i, InputRoutingData<EventHandlerGlobalIndex>& data) {}
+    virtual void insertRoutingData (Interval& i, InputRoutingData<EventHandlerLocalIndex>& data) {}
+    virtual void processEvent (double t, int id) {};
+    virtual bool needFewPoints () const { return false; }
+    virtual DirectRouter* directRouter () { return 0; }; //Remove this later
+  };
+
+  template<class RoutingData, class IntervalLookup>
+  class IntervalProcessingRouter : public EventRouter {
+    class Processor : public IntervalLookup::Action {
+    protected:
+      double t_;
+      int id_;
+    public:
+      Processor (double t, int id) : t_ (t), id_ (id) { };
+      void operator() (RoutingData& data)
+      {
+	/* remedius
+	 * for Global index ((RoutingData &)data).offset () is set to 0 during
+	 * SpatialNegotiator::wrapIntervals();
+	 */
+	data.process (t_, id_ - data.offset ());
+      }
+    };
+    
+    IntervalLookup routingTable;
+  public:
+    void insertRoutingData (Interval& i, RoutingData& data);
+    void buildTable ();
+    void processEvent (double t, int id);
+  };
+
+  template<class RoutingData, class IntervalLookup>
+  void
+  IntervalProcessingRouter<RoutingData, IntervalLookup>::insertRoutingData (Interval& i,
+									    RoutingData &data)
+  {
+    routingTable.add (i, data);
+  }
+
+
+  template<class RoutingData, class IntervalLookup>
+  void
+  IntervalProcessingRouter<RoutingData, IntervalLookup>::buildTable ()
+  {
+    routingTable.build ();
+  }
+
+  template<class RoutingData, class IntervalLookup>
+  void
+  IntervalProcessingRouter<RoutingData, IntervalLookup>::processEvent (double t, int id)
+  {
+    Processor i (t, id);
+    routingTable.search (id, &i);
+  }
+
+  class TreeProcessingOutputRouter
+    : public IntervalProcessingRouter<OutputRoutingData,
+				      IntervalTree<int, Interval, OutputRoutingData> >
+  {
+  };
+
+  class TreeProcessingInputGlobalRouter
+    : public IntervalProcessingRouter<InputRoutingData<EventHandlerGlobalIndex>,
+				      IntervalTree<int,
+						   Interval,
+						   InputRoutingData<EventHandlerGlobalIndex> > >
+  {
+  };
+
+  class TreeProcessingInputLocalRouter
+    : public IntervalProcessingRouter<InputRoutingData<EventHandlerLocalIndex>,
+				      IntervalTree<int,
+						   Interval,
+						   InputRoutingData<EventHandlerLocalIndex> > >
+  {
+  };
+
+  class TableProcessingOutputRouter
+    : public IntervalProcessingRouter<OutputRoutingData,
+				      IntervalTable<int, Interval, OutputRoutingData> >
+  {
+  public:
+    bool needFewPoints () const { return true; }
+  };
+
+  class TableProcessingInputGlobalRouter
+    : public IntervalProcessingRouter<InputRoutingData<EventHandlerGlobalIndex>,
+				      IntervalTable<int,
+						    Interval,
+						    InputRoutingData<EventHandlerGlobalIndex> > >
+  {
+  public:
+    bool needFewPoints () const { return true; }
+  };
+
+  class TableProcessingInputLocalRouter
+    : public IntervalProcessingRouter<InputRoutingData<EventHandlerLocalIndex>,
+				      IntervalTable<int,
+						    Interval,
+						    InputRoutingData<EventHandlerLocalIndex> > >
+  {
+  public:
+    bool needFewPoints () const { return true; }
+  };
+
+  class DirectRouter : public EventRouter {
+    char* buffer_;
+    unsigned int size_;
+    unsigned int pos_;
+    std::vector<char> extra_;
+  public:
+    DirectRouter () : size_ (0), pos_ (0) { }
+    DirectRouter* directRouter () { return this; }; //Remove this later
+    unsigned int dataSize () { return pos_ + extra_.size (); }
+    inline void processEvent (double t, int id)
+    {
+      if (pos_ < size_)
+	{
+	  Event* e = static_cast<Event*> (static_cast<void*> (buffer_ + pos_));
+	  e->t = t;
+	  e->id = id;
+	  pos_ += sizeof (Event);
+	}
+      else
+	processExtra (t, id);
+    }
+    void processExtra (double t, int id);
+    void setOutputBuffer (void* buffer, unsigned int size);
+    void fillOutputBuffer () { pos_ = 0; }
+  };
+
+  class HybridTreeProcessingOutputRouter
+    : public TreeProcessingOutputRouter
+  {
+  private:
+    DirectRouter directRouter_;
+  public:
+    DirectRouter* directRouter () { return &directRouter_; }
+    inline void processEvent (double t, int id)
+    {
+      TreeProcessingOutputRouter::processEvent (t, id);
+      directRouter_.processEvent (t, id);
+    }
+  };
+
+  class HybridTableProcessingOutputRouter
+    : public TableProcessingOutputRouter
+  {
+  private:
+    DirectRouter directRouter_;
+  public:
+    DirectRouter* directRouter () { return &directRouter_; }
+    inline void processEvent (double t, int id)
+    {
+      TableProcessingOutputRouter::processEvent (t, id);
+      directRouter_.processEvent (t, id);
+    }
+  };
+
+}
+#define MUSIC_EVENT_ROUTER_HH
+#endif
diff --git a/src/music/event_routing_map.hh b/src/music/event_routing_map.hh
new file mode 100644
index 0000000..e47a3b5
--- /dev/null
+++ b/src/music/event_routing_map.hh
@@ -0,0 +1,127 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/* remedius
+ * event_routingmap.hh and event_routingmap.cc were added to the repository
+ * as a new hierarchy for EventRoutingMap class.
+ * Before EventRoutingMap class was defined in event_router.cc file.
+ * EventRoutingMap class keeps the former methods however it became a template
+ * due to different data types needed for processing events on the receiver and sender sides.
+ */
+#ifndef MUSIC_EVENT_ROUTINGMAP_HH
+#include <map>
+#include <vector>
+#include <music/FIBO.hh>
+#include <music/interval_tree.hh>
+#include <music/index_map.hh>
+#include <music/event.hh>
+
+namespace MUSIC {
+
+  class EventRouter;
+
+  template <class DataType>
+  class EventRoutingMap{
+  public:
+    virtual ~EventRoutingMap ();
+    virtual void fillRouter (EventRouter *router)=0;
+    virtual void insert (IndexInterval i, DataType data);
+  protected:
+    typedef std::map<DataType, std::vector<IndexInterval *> >DataMap;
+    DataMap dataMap;
+    EventRoutingMap () {}
+    std::vector<IndexInterval> rebuildIntervals (std::vector<IndexInterval*> &intervals);
+    struct comp{
+      bool operator() (IndexInterval* i,IndexInterval *j) { return (*i<*j);}
+    } comp_obj;
+
+
+  };
+  template<class DataType>
+  EventRoutingMap<DataType>::~EventRoutingMap(){
+    typename DataMap::iterator pos;
+    for (pos = dataMap.begin (); pos != dataMap.end (); ++pos)
+      for (std::vector<IndexInterval *>::iterator i =
+	     pos->second.begin (); i != pos->second.end (); i++)
+	delete (*i);
+  }
+  template<class DataType>
+  void
+  EventRoutingMap<DataType>::insert (IndexInterval i, DataType data)
+  {
+    dataMap[data].push_back (new IndexInterval(i.begin(),i.end(),i.local()));
+  }
+  template<class DataType>
+  std::vector<IndexInterval>
+  EventRoutingMap<DataType>::rebuildIntervals (std::vector<IndexInterval*> &intervals)
+  {
+    std::vector<IndexInterval> newIntervals;
+
+    // Sort all intervals
+    sort (intervals.begin (), intervals.end (), comp_obj);
+    std::vector<IndexInterval *>::iterator i = intervals.begin ();
+
+
+    // Build sequence of unions out of the original interval sequence
+    i = intervals.begin ();
+    while (i != intervals.end ())
+      {
+	IndexInterval current = **i++;
+
+	while (i != intervals.end ()
+	       && (*i)->begin () <= current.end ())
+	  {
+	    // join intervals
+	    int maxEnd = std::max<int> (current.end (), (*i)->end ());
+	    current.setEnd (maxEnd);
+	    ++i;
+	  }
+
+	newIntervals.push_back (current);
+      }
+
+    return newIntervals;
+  }
+  /* remedius
+   * InputRoutingMap is an EventRoutingMap that's used for processing the events on the receiver side
+   */
+
+  class InputRoutingMap:public EventRoutingMap<EventHandlerPtr*>
+  {
+  public:
+    void fillRouter (EventRouter *router);
+  private:
+    void insertRoutingInterval(EventRouter *router, IndexInterval i, EventHandlerPtr *h);
+  };
+
+  /* remedius
+   * OutputRoutingMap is an EventRoutingMap that's used for processing the events on the sender side
+   */
+  class OutputRoutingMap:public EventRoutingMap<FIBO*>
+  {
+    std::vector<IndexInterval*> *intervals;
+  public:
+    OutputRoutingMap(){intervals = new std::vector<IndexInterval *>;}
+    ~OutputRoutingMap();
+    void fillRouter (EventRouter *router);
+    void insert (IndexInterval i, FIBO* data);
+  private:
+    void insertRoutingInterval(EventRouter *router, IndexInterval i, FIBO *b);
+  };
+}
+#define MUSIC_EVENT_ROUTINGMAP_HH
+#endif
diff --git a/src/music/index_map.hh b/src/music/index_map.hh
new file mode 100644
index 0000000..c4b1a26
--- /dev/null
+++ b/src/music/index_map.hh
@@ -0,0 +1,113 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_INDEX_MAP_HH
+#include <memory>
+
+#include <music/interval.hh>
+
+namespace MUSIC {
+
+  class Index {
+  public:
+    enum Type { GLOBAL, LOCAL, UNDEFINED };
+    static int WILDCARD_MAX;
+  };
+
+  class GlobalIndex : public Index {
+    int id;
+  public:
+    GlobalIndex () { }
+    GlobalIndex (int i) : id (i) { }
+    operator int () const { return id; }
+  };
+
+  class LocalIndex : public Index {
+    int id;
+  public:
+    LocalIndex () { }
+    LocalIndex (int i) : id (i) { }
+    operator int () const { return id; }
+  };
+
+  class IndexInterval : public Interval {
+    LocalIndex local_;
+  public:
+    IndexInterval () { }
+    IndexInterval (GlobalIndex b, GlobalIndex e, LocalIndex l)
+      : Interval (b, e), local_ (l) { }
+    LocalIndex local () const { return local_; }
+    void setLocal (int l) { local_ = l; }
+  };
+
+  bool operator< (const IndexInterval& a, const IndexInterval& b);
+
+  class IndexMap {
+  public:
+    class IteratorImplementation {
+    public:
+      virtual ~IteratorImplementation () { }
+      virtual const IndexInterval operator* () = 0;
+      virtual const IndexInterval* dereference () = 0;
+      virtual bool isEqual (IteratorImplementation* i) const = 0;
+      virtual void operator++ () = 0;
+      virtual IteratorImplementation* copy () = 0;
+    };
+
+    
+    class iterator {
+      IteratorImplementation* implementation_;
+    public:
+      iterator (IteratorImplementation* impl)
+	: implementation_ (impl) { }
+      ~iterator ()
+      {
+	delete implementation_;
+      }
+      iterator (const iterator& i)
+	: implementation_ (i.implementation_->copy ())
+      {
+      }
+      const iterator& operator= (const iterator& i)
+      {
+	delete implementation_;
+	implementation_ = i.implementation_->copy ();
+	return *this;
+      }
+      IteratorImplementation* implementation () const
+      {
+	return implementation_;
+      }
+      const IndexInterval operator* ();
+      const IndexInterval* operator-> ();
+      bool operator== (const iterator& i) const;
+      bool operator!= (const iterator& i) const;
+      iterator& operator++ ();
+    };
+    
+
+    virtual ~IndexMap () { }
+    virtual iterator begin () = 0;
+    virtual const iterator end () const = 0;
+
+    virtual IndexMap* copy () = 0;
+  };
+
+}
+#define MUSIC_INDEX_MAP_HH
+#endif
diff --git a/src/music/index_map_factory.hh b/src/music/index_map_factory.hh
new file mode 100644
index 0000000..dabfc83
--- /dev/null
+++ b/src/music/index_map_factory.hh
@@ -0,0 +1,57 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_INDEX_MAP_FACTORY_HH
+#include <vector>
+
+#include "music/index_map.hh"
+
+namespace MUSIC {
+
+  class IndexMapFactory : public IndexMap {
+    std::vector<IndexInterval> indices_;
+  public:
+    class iterator : public IndexMap::IteratorImplementation {
+      const IndexInterval* intervalPtr;
+    public:
+      iterator (const IndexInterval* ptr) : intervalPtr (ptr) { }
+      virtual const IndexInterval operator* () { return *intervalPtr; }
+      virtual const IndexInterval* dereference () { return intervalPtr; }
+      virtual bool isEqual (IteratorImplementation* i) const
+      {
+	return intervalPtr == static_cast<iterator*> (i)->intervalPtr;
+      }
+      virtual void operator++ () { ++intervalPtr; }
+      virtual IteratorImplementation* copy ()
+      {
+	return new iterator (intervalPtr);
+      }
+    };
+    
+    IndexMapFactory ();
+    IndexMapFactory (std::vector<IndexInterval>& indices);
+    void add (int begin, int end, int local);
+    void build ();
+    virtual IndexMap::iterator begin ();
+    virtual const IndexMap::iterator end () const;
+    virtual IndexMap* copy ();    
+  };
+
+}
+#define MUSIC_INDEX_MAP_FACTORY_HH
+#endif
diff --git a/src/music/interval.hh b/src/music/interval.hh
new file mode 100644
index 0000000..2412e5a
--- /dev/null
+++ b/src/music/interval.hh
@@ -0,0 +1,48 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_INTERVAL_HH
+
+#include <ostream>
+
+namespace MUSIC {
+
+  class Interval {
+    int begin_;
+    int end_;
+  public:
+    Interval () { }
+    Interval (int b, int e) : begin_ (b), end_ (e) { }
+    ~Interval () { }
+    int begin () const { return begin_; }
+    int end () const { return end_; }
+    void setBegin (int begin) { begin_ = begin; }
+    void setEnd (int end) { end_ = end; }
+    bool operator< (const Interval& data) const
+    {
+      return begin () < data.begin ();
+    }
+
+  };
+
+  // support printed representation
+  std::ostream& operator<< (std::ostream& os, const Interval& ival);
+
+}
+#define MUSIC_INTERVAL_HH
+#endif
diff --git a/src/music/interval_table.hh b/src/music/interval_table.hh
new file mode 100644
index 0000000..959f9b7
--- /dev/null
+++ b/src/music/interval_table.hh
@@ -0,0 +1,383 @@
+/*
+ *  This file is distributed together with MUSIC.
+ *  Copyright (C) 2008, 2009 Mikael Djurfeldt
+ *
+ *  This interval table implementation 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; either version 3 of the License, or (at your option)
+ *  any later version.
+ *
+ *  The interval table implementation 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_INTERVAL_TABLE_HH
+
+/*
+ * The interval table implementation can be adjusted by defining the
+ * preprocessor macro MUSIC_ITABLE_FLAVOR to one of the following:
+ */
+
+#define MUSIC_VANILLA   0 // intervals stored in a linked list in one
+			  // contiguous memory block
+
+#define MUSIC_TRIMMED   1 // linked list block trimmed during build
+
+#define MUSIC_COMPACT   2 // linked list block freed during build and
+			  // replaced by a single array of intervals
+
+#define MUSIC_SCATTERED 3 // list block freed during build and
+			  // replaced by many small arrays of
+			  // intervals---one per key in the table
+
+#ifndef MUSIC_ITABLE_FLAVOR
+#define MUSIC_ITABLE_FLAVOR MUSIC_VANILLA
+#endif
+
+//#define MUSIC_ITABLE_COMPRESSED
+
+#include <vector>
+#include <map>
+#include <limits>
+#include <algorithm>
+//#include <hash_map>
+
+extern "C" {
+#include <assert.h>
+}
+
+#include "ordered_ilist.hh"
+
+namespace MUSIC {
+
+  template<class PointType, class IntervalType, class DataType>
+  class IntervalTable {
+  private:
+    typedef unsigned short DataIndex;
+    static const DataIndex MAXDATA = 65535;
+
+    typedef OrderedIList<DataIndex> IList;
+
+    class PreEntry {
+      IList list_;
+      IList hint_;
+    public:
+      PreEntry () : list_ (IList::NIL), hint_ (list_) { }
+      IList list () { return list_; }
+      void insert (DataIndex i) { hint_ = list_.insert (i, hint_); }
+    };
+
+    // was hash_map
+    typedef std::map<PointType, PreEntry> PreEntryMap;
+    PreEntryMap* preEntryMap_;
+
+    class Entry {
+#ifdef MUSIC_ITABLE_COMPRESSED
+      PointType key_;
+#endif
+#if MUSIC_ITABLE_FLAVOR == MUSIC_VANILLA || MUSIC_ITABLE_FLAVOR == MUSIC_TRIMMED
+      IList ls_;
+    public:
+#ifdef MUSIC_ITABLE_COMPRESSED
+      Entry (PointType key) : key_ (key), ls_ (IList::NIL) { }
+      Entry (PointType key, IList ls) : key_ (key), ls_ (ls) { }
+#else
+      Entry () : ls_ (IList::NIL) { }
+      Entry (IList ls) : ls_ (ls) { }
+#endif
+      IList list () { return ls_; }
+#else
+      DataIndex n_;
+      IList::Interval* ivals_;
+    public:
+#ifdef MUSIC_ITABLE_COMPRESSED
+      Entry (PointType key)
+	: key_ (key), n_ (0), ivals_ (NULL) { }
+      Entry (PointType key, IList::Interval* ivals, int n)
+	: key_ (key), n_ (n), ivals_ (ivals) { }
+#else
+      Entry ()
+	: n_ (0), ivals_ (NULL) { }
+      Entry (IList::Interval* ivals, int n)
+	: n_ (n), ivals_ (ivals) { }
+#endif
+      IList::Interval* intervals () const { return ivals_; }
+      int nIntervals () const { return n_; }
+#endif
+#ifdef MUSIC_ITABLE_COMPRESSED
+      PointType key () { return key_; }
+#endif
+    };
+
+    std::vector<Entry> entryTable_;
+    std::vector<DataType> data_;
+#if MUSIC_ITABLE_FLAVOR == MUSIC_COMPACT
+    IList::Interval* iArray;
+#endif
+
+    class SortCriterion {
+      // We use this ugly hack in order to be able to use the stl::map
+      // for looking up Data indices. The more proper approach is to
+      // include a hash map implementation in MUSIC. We might use one
+      // of Googles sparse_map implementations.
+      struct Mem0 {
+	int f0;
+      };
+      struct Mem1 {
+	void* f0;
+      };
+      struct Mem2 {
+	int f0;
+	void* f1;
+      };
+    public:
+      bool operator() (const DataType& x, const DataType& y) const
+      {
+	const DataType* px = &x;
+	const DataType* py = &y;
+	// the compiler optimization will resolve this at compile time
+	if (sizeof (DataType) == sizeof (Mem0))
+	  {
+	    const Mem0 u = *reinterpret_cast<const Mem0*> (px);
+	    const Mem0 v = *reinterpret_cast<const Mem0*> (py);
+	    return u.f0 < v.f0;
+	  }
+	else if (sizeof (DataType) == sizeof (Mem1))
+	  {
+	    const Mem1 u = *reinterpret_cast<const Mem1*> (px);
+	    const Mem1 v = *reinterpret_cast<const Mem1*> (py);
+	    return u.f0 < v.f0;
+	  }
+	else if (sizeof (DataType) == sizeof (Mem2))
+	  {
+	    const Mem2 u = *reinterpret_cast<const Mem2*> (px);
+	    const Mem2 v = *reinterpret_cast<const Mem2*> (py);
+	    return u.f1 < v.f1 || (u.f1 == v.f1 && u.f0 < v.f0);
+	  }
+	else
+	  {
+	    // report error
+	    assert (sizeof (DataType) == sizeof (Mem0));
+	    return false; // satisfy compiler
+	  }
+      }
+    };
+
+    typedef std::map<DataType, DataIndex, SortCriterion> DataMap;
+    DataMap* dataMap_;
+
+    PointType lowerBound_;
+    PointType rangeSize_;
+    unsigned int tableSize_;
+    void recordProperties (const IntervalType& ival);
+
+    unsigned int nIntervals_;
+
+  public:
+    class Action {
+    public:
+      virtual void operator() (DataType& data) = 0;
+    };
+
+    IntervalTable ()
+      : lowerBound_ (std::numeric_limits<PointType>::max ()),
+	rangeSize_ (std::numeric_limits<PointType>::min ()),
+	tableSize_ (0),
+	nIntervals_ (0)
+    {
+      preEntryMap_ = new PreEntryMap ();
+      dataMap_ = new DataMap ();
+    }
+    ~IntervalTable ()
+    {
+#if MUSIC_ITABLE_FLAVOR == MUSIC_COMPACT
+      delete[] iArray;
+#elif MUSIC_ITABLE_FLAVOR == MUSIC_SCATTERED
+      for (typename std::vector<Entry>::iterator i = entryTable_.begin ();
+	   i != entryTable_.end ();
+	   ++i)
+	delete[] i->intervals();
+#endif
+    }
+    void add (const IntervalType& i, const DataType& data);
+    void build ();
+    void search (PointType point, Action* a);
+    int size () const { return nIntervals_; }
+    int tableSize () const { return entryTable_.size (); }
+  };
+
+  template<class PointType, class IntervalType, class DataType>
+  void
+  IntervalTable<PointType, IntervalType, DataType>::recordProperties
+  (const IntervalType& ival)
+  {
+    lowerBound_ = std::min (lowerBound_, ival.begin ());
+    rangeSize_ = std::max (rangeSize_, ival.end ());
+    nIntervals_ += 1;
+  }
+
+  template<class PointType, class IntervalType, class DataType>
+  void
+  IntervalTable<PointType, IntervalType, DataType>::add (const IntervalType& ival,
+							 const DataType& data)
+  {
+    // assign a DataIndex to data
+    typename DataMap::iterator pos = dataMap_->find (data);
+    DataIndex dataIndex;
+    if (pos == dataMap_->end ())
+      {
+	dataIndex = data_.size ();
+	assert (dataIndex < MAXDATA);
+	data_.push_back (data);
+	(*dataMap_)[data] = dataIndex;
+      }
+    else
+      dataIndex = pos->second;
+
+    recordProperties (ival);
+
+    for (PointType k = ival.begin (); k < ival.end (); ++k)
+      (*preEntryMap_)[k].insert (dataIndex);
+  }
+
+
+  template<class PointType, class IntervalType, class DataType>
+  void
+  IntervalTable<PointType, IntervalType, DataType>::build ()
+  {
+    delete dataMap_;
+    // trim data_;
+    std::vector<DataType> (data_).swap (data_);
+    tableSize_ = preEntryMap_->size ();
+    if (rangeSize_ > 0)
+      rangeSize_ = rangeSize_ - lowerBound_;
+    else
+      rangeSize_ = 0; // no intervals
+#ifdef MUSIC_ITABLE_COMPRESSED
+    if (rangeSize_ == 0)
+      rangeSize_ = 1;
+    entryTable_.reserve (tableSize_ + 2);
+#else
+    entryTable_.resize (rangeSize_);
+#endif
+#if MUSIC_ITABLE_FLAVOR == MUSIC_COMPACT || MUSIC_ITABLE_FLAVOR == MUSIC_SCATTERED
+    IList::Interval* iPtr;
+#if MUSIC_ITABLE_FLAVOR == MUSIC_COMPACT
+    iArray = new IList::Interval[IList::nNodes ()];
+    iPtr = iArray;
+#endif
+#endif
+#ifdef MUSIC_ITABLE_COMPRESSED
+    // backward sentinel
+    entryTable_.push_back (Entry (std::numeric_limits<PointType>::min ()));
+#endif
+    for (typename PreEntryMap::iterator p = preEntryMap_->begin ();
+	 p != preEntryMap_->end ();
+	 ++p)
+      {
+	PointType key = p->first;
+	IList list = p->second.list ();
+#if MUSIC_ITABLE_FLAVOR == MUSIC_VANILLA || MUSIC_ITABLE_FLAVOR == MUSIC_TRIMMED
+#ifdef MUSIC_ITABLE_COMPRESSED
+	entryTable_.push_back (Entry (key, list));
+#else
+	entryTable_[key - lowerBound_] = Entry (list);
+#endif
+#else // MUSIC_COMPACT or MUSIC_SCATTERED
+	int n = list.size ();
+#if MUSIC_ITABLE_FLAVOR == MUSIC_SCATTERED
+	iPtr = new IList::Interval[n];
+#endif
+#ifdef MUSIC_ITABLE_COMPRESSED
+	entryTable_.push_back (Entry (key, iPtr, n));
+#else
+	entryTable_[key - lowerBound_] = Entry (iPtr, n);
+#endif
+	for (IList::iterator j = list.begin (); j != list.end (); ++j)
+	  *iPtr++ = *j;
+#endif
+      }
+#ifdef MUSIC_ITABLE_COMPRESSED
+    // forward sentinel
+    entryTable_.push_back (Entry (std::numeric_limits<PointType>::max ()));
+#endif
+    delete preEntryMap_;
+#if MUSIC_ITABLE_FLAVOR == MUSIC_TRIMMED
+    IList::trimNodes ();
+#elif MUSIC_ITABLE_FLAVOR == MUSIC_COMPACT || MUSIC_ITABLE_FLAVOR == MUSIC_SCATTERED
+    IList::reset ();
+#endif
+
+#ifdef MUSIC_DEBUG
+    std::cout << "data: " << data_.size () << std::endl
+	      << "nodes: " << IList::nNodes () << std::endl
+	      << "freelist: " << IList::freeList ().size ()
+	      << std::endl;
+#endif
+  }
+  
+  
+  template<class PointType, class IntervalType, class DataType>
+  void
+  IntervalTable<PointType, IntervalType, DataType>::search (PointType p, Action* a)
+  {
+#ifndef MUSIC_ITABLE_COMPRESSED
+    PointType i = p - lowerBound_;
+    if (i < 0 || i >= rangeSize_)
+      return;
+#else
+    // obtain approximate position
+    PointType i = ((p - lowerBound_) * tableSize_) / rangeSize_ + 1;
+
+    // sentinels are at 0 and tableSize_ + 1
+    if (i < 1 || i > PointType (tableSize_))
+      return;
+
+    if (p != entryTable_[i].key ())
+      {
+	// search forward
+	if (p > entryTable_[i].key ())
+	  {
+	    do
+	      ++i;
+	    // end of table guarded by sentinel
+	    while (p > entryTable_[i].key ());
+	    if (p != entryTable_[i].key ())
+	      return;
+	  }
+	else
+	  // search backward
+	  {
+	    do
+	      --i;
+	    // beginning of table guarded by sentinel
+	    while (p < entryTable_[i].key ());
+	    if (p != entryTable_[i].key ())
+	      return;
+	  }
+      }
+#endif
+
+#if MUSIC_ITABLE_FLAVOR == MUSIC_VANILLA || MUSIC_ITABLE_FLAVOR == MUSIC_TRIMMED
+    IList ls = entryTable_[i].list ();
+    for (IList::iterator j = ls.begin (); j != ls.end (); ++j)
+      for (int k = j->begin (); k <= j->end (); ++k)
+	(*a) (data_[k]);
+#else // MUSIC_COMPACT or MUSIC_SCATTERED
+    IList::Interval* ivals = entryTable_[i].intervals ();
+    for (int j = 0; j < entryTable_[i].nIntervals (); ++j)
+      for (int k = ivals[j].begin (); k <= ivals[j].end (); ++k)
+	(*a) (data_[k]);
+#endif
+  }
+
+}
+
+#define MUSIC_INTERVAL_TABLE_HH
+#endif
diff --git a/src/music/interval_tree.hh b/src/music/interval_tree.hh
new file mode 100644
index 0000000..192d16e
--- /dev/null
+++ b/src/music/interval_tree.hh
@@ -0,0 +1,190 @@
+/*
+ *  This file is distributed together with MUSIC.
+ *  Copyright (C) 2008, 2009 Mikael Djurfeldt
+ *
+ *  This interval tree implementation 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; either version 3 of the License, or (at your option)
+ *  any later version.
+ *
+ *  The interval tree implementation 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_INTERVAL_TREE_HH
+
+#include <vector>
+#include <limits>
+#include <algorithm>
+
+namespace MUSIC {
+
+  template<class PointType, class IntervalType, class DataType>
+  class IntervalTree {
+    static const int ROOT = 0;
+
+    // class NodeType needs to be public on BG machines
+  public:
+    class NodeType {
+      IntervalType ival_;
+      PointType maxEnd_;
+      DataType data_;
+    public:
+      NodeType () { }
+      NodeType (const IntervalType& i, const DataType& d)
+	: ival_ (i), maxEnd_ (minVal ()), data_ (d) { }
+      NodeType (const IntervalType& i, const PointType m, const DataType& d)
+	: ival_ (i), maxEnd_ (m), data_ (d) { }
+      NodeType& operator= (const NodeType& node)
+      {
+	ival_ = node.ival_;
+	maxEnd_ = node.maxEnd_;
+	data_ = node.data_;
+	return *this;
+      }
+      static PointType minVal () {
+	return std::numeric_limits<PointType>::min ();
+      }
+      bool operator< (const NodeType& other) const {
+	return begin () < other.begin ();
+      }
+      IntervalType& interval () { return ival_; }
+      DataType& data () { return data_; }
+      PointType begin () const { return ival_.begin (); }
+      PointType end () const { return ival_.end (); }
+      PointType maxEnd () const { return maxEnd_; }
+    };
+
+  private:
+    std::vector<NodeType> nodes;
+    int leftChild (int i) const { return 2 * i + 1; }
+    int rightChild (int i) const { return 2 * i + 2; }
+    int computeSize () const;
+    int maxIndex (int l, int r, int i) const;
+    PointType build (std::vector<NodeType>& dest, int l, int r, int i);
+
+  public:
+    class Action {
+    public:
+      virtual void operator() (DataType& data) = 0;
+    };
+
+  private:
+    void search (unsigned int i, PointType point, Action* a);
+
+  public:
+    void add (const IntervalType& i, const DataType& data);
+    void build ();
+    void search (PointType point, Action* a);
+    int size () const { return nodes.size (); }
+  };
+
+  template<class PointType, class IntervalType, class DataType>
+  void
+  IntervalTree<PointType, IntervalType, DataType>::add (const IntervalType& i,
+							const DataType& data)
+  {
+    nodes.push_back (NodeType (i, data));
+  }
+
+
+  template<class PointType, class IntervalType, class DataType>
+  int
+  IntervalTree<PointType, IntervalType, DataType>::computeSize () const
+  {
+    return maxIndex (0, nodes.size (), ROOT) + 1;
+  }
+
+  
+  template<class PointType, class IntervalType, class DataType>
+  int
+  IntervalTree<PointType, IntervalType, DataType>::maxIndex (int l, int r, int i) const
+  {
+    if (l >= r)
+      return -1;
+    int m = (l + r) / 2;
+    int max = i;
+    max = std::max (max, maxIndex (l, m, leftChild (i)));
+    return std::max (max, maxIndex (m + 1, r, rightChild (i)));
+  }  
+
+  
+  template<class PointType, class IntervalType, class DataType>
+  void
+  IntervalTree<PointType, IntervalType, DataType>::build ()
+  {
+    sort (nodes.begin (), nodes.end ());
+    std::vector<NodeType> newNodes (computeSize ());
+    build (newNodes, 0, nodes.size (), ROOT);
+    nodes = newNodes;
+  }
+  
+  
+  template<class PointType, class IntervalType, class DataType>
+  PointType
+  IntervalTree<PointType, IntervalType, DataType>::build (std::vector<NodeType>& dest,
+							  int l,
+							  int r,
+							  int i)
+  {
+    if (l < r) // sequence not empty
+      {
+	int m = (l + r) / 2;
+	PointType max = nodes[m].end ();
+	PointType end = build (dest, l, m, leftChild (i));
+	max = end < max ? max : end;
+	end = build (dest, m + 1, r, rightChild (i));
+	max = end < max ? max : end;
+	dest[i] = NodeType (nodes[m].interval (), max, nodes[m].data ());
+	return max;
+      }
+    else
+      return NodeType::minVal ();
+  }
+
+
+  template<class PointType, class IntervalType, class DataType>
+  void
+  IntervalTree<PointType, IntervalType, DataType>::search (PointType p, Action* a)
+  {
+    search (ROOT, p, a);
+  }
+
+  template<class PointType, class IntervalType, class DataType>
+  void
+  IntervalTree<PointType, IntervalType, DataType>::search (unsigned int i,
+							   PointType p,
+							   Action* a)
+  {
+    // Newly introduced extra stop condition enabling less memory usage
+    if (i >= nodes.size ())
+      return;
+
+    // this condition both checks if the point is to the right of all
+    // nodes in this subtree (and previously stopped recursion at
+    // noNode values)
+    if (p >= nodes[i].maxEnd ())
+      return;
+
+    search (leftChild (i), p, a);
+
+    if (p < nodes[i].begin ())
+      // point is to the left of this interval and of the right subtree
+      return;
+
+    if (p < nodes[i].end ())
+      // perform action on this interval
+      (*a) (nodes[i].data ());
+
+    search (rightChild (i), p, a);
+  }
+}
+
+#define MUSIC_INTERVAL_TREE_HH
+#endif
diff --git a/src/music/ioutils.hh b/src/music/ioutils.hh
new file mode 100644
index 0000000..df7c024
--- /dev/null
+++ b/src/music/ioutils.hh
@@ -0,0 +1,34 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_IOUTILS_HH
+#include <sstream>
+
+namespace MUSIC {
+
+  namespace IOUtils {
+    // NOTE: these could be stream classes
+    void write (std::ostringstream& out, std::string s);
+    std::string read (std::istringstream& in, int delim);
+    std::string read (std::istringstream& in);
+  }
+
+}
+
+#define MUSIC_IOUTILS_HH
+#endif
diff --git a/src/music/linear_index.hh b/src/music/linear_index.hh
new file mode 100644
index 0000000..8964779
--- /dev/null
+++ b/src/music/linear_index.hh
@@ -0,0 +1,54 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_LINEAR_INDEX_HH
+#include "music/index_map.hh"
+
+namespace MUSIC {
+
+  /*
+   * This index map is part of the MUSIC API and documented
+   * in section 4.3.8 of the MUSIC manual.
+   */
+
+  class LinearIndex : public IndexMap {
+    IndexInterval interval_;
+  public:
+    class iterator : public IndexMap::IteratorImplementation {
+      LinearIndex* indices_;
+    public:
+      iterator (LinearIndex* li);
+      virtual const IndexInterval operator* ();
+      virtual const IndexInterval* dereference ();
+      virtual bool isEqual (IteratorImplementation* i) const;
+      virtual void operator++ ();
+      virtual IteratorImplementation* copy ()
+      {
+	return new iterator (indices_);
+      }
+    };
+
+    LinearIndex (GlobalIndex baseindex, int size);
+    virtual IndexMap::iterator begin ();
+    virtual const IndexMap::iterator end () const;
+    virtual IndexMap* copy ();
+  };
+
+}
+#define MUSIC_LINEAR_INDEX_HH
+#endif
diff --git a/src/music/memory.hh b/src/music/memory.hh
new file mode 100644
index 0000000..04ac350
--- /dev/null
+++ b/src/music/memory.hh
@@ -0,0 +1,28 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_MEMORY_HH
+
+namespace MUSIC {
+
+  void reportMem ();
+
+}
+
+#define MUSIC_MEMORY_HH
+#endif
diff --git a/src/music/message.hh b/src/music/message.hh
new file mode 100644
index 0000000..e3cf773
--- /dev/null
+++ b/src/music/message.hh
@@ -0,0 +1,75 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_MESSAGE_HH
+#include <music/index_map.hh>
+
+namespace MUSIC {
+
+  class MessageHeader {
+  public:
+    typedef struct {
+      double t;
+      int size;
+    } header_t;
+
+  private:
+    union {
+      header_t header;
+      char data[sizeof (header_t)];
+    } u;
+    
+  public:
+    MessageHeader (double t, int size)
+    {
+      u.header.t = t;
+      u.header.size = size;
+    }
+
+    double t () { return u.header.t; }
+    double size () { return u.header.size; }
+    void* data () { return u.data; }
+  };
+
+  class MessageHandler {
+  public:
+    virtual void operator () (double t, void* msg, size_t size) = 0;
+    virtual ~MessageHandler() {}
+  };
+  
+  class MessageHandlerDummy : public MessageHandler {
+  public:
+    virtual void operator () (double t, void* msg, size_t size) { };
+  };
+  
+  class MessageHandlerProxy
+    : public MessageHandler {
+    void (*messageHandler) (double t, void* msg, size_t size);
+  public:
+    MessageHandlerProxy () { }
+    MessageHandlerProxy (void (*mh) (double t, void* msg, size_t size))
+      : messageHandler (mh) { }
+    void operator () (double t, void* msg, size_t size)
+    {
+      messageHandler (t, msg, size);
+    }
+  };
+
+}
+#define MUSIC_MESSAGE_HH
+#endif
diff --git a/src/music/multibuffer.hh b/src/music/multibuffer.hh
new file mode 100644
index 0000000..6a8bdef
--- /dev/null
+++ b/src/music/multibuffer.hh
@@ -0,0 +1,374 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_MULTIBUFFER_HH
+
+#define MUSIC_TWOSTAGE_ALLGATHER
+
+#include "music/music-config.hh"
+
+#include "music/connector.hh"
+
+#include <vector>
+#include <set>
+#include <map>
+#include <string>
+
+#if MUSIC_USE_MPI
+
+namespace MUSIC {
+
+  class Updateable {
+  public:
+    virtual ~Updateable () { }
+    virtual void update () = 0;
+  };
+
+  class MultiConnector;
+
+  class MultiBuffer {
+    /*
+     * The buffer is organized as a sequence of BLOCKs.  Each BLOCK
+     * starts with an ERRORFLAG (HeaderType).
+     *
+     * When ERRORFLAG is clear, it is followed by a sequence of
+     * BUFFERs. Each BUFFER starts with current SIZE of data followed
+     * by DATA.
+     *
+     * When the ERRORFLAG is set, it is followed by a sequence of
+     * requested buffer sizes.
+     *
+     * A block with a set ERRORFLAG is prepared at and sent from
+     * displacement 0.
+     *
+     * inputConnectorMap associates each Connector with an
+     * InputSubconnectorInfo.  This data structure contains a vector
+     * of BufferInfo, one for each rank in the corresponding
+     * OutputConnector.
+     *
+     * outputConnectorMap associates each OutputConnector with an
+     * OutputSubconnectorInfo containing a pointer to the BufferInfo
+     * corresponding to this rank.
+     */
+  public:
+    typedef char* BufferType;
+
+    struct RankInfo {
+      RankInfo () { }
+      RankInfo (int l, int lr)
+	: leader (l), localRank (lr) { }
+      int leader;
+      int localRank;
+    };
+
+    typedef std::map<int, std::vector<int> > RankMap;
+
+    struct Interval {
+      Interval () { }
+      Interval (int f, int l) : first (f), last (l) { }
+      int first;
+      int last;
+    };
+
+    typedef std::vector<Interval> Intervals;
+    typedef std::map<unsigned int, Intervals> GroupMap;
+  private:
+    static const unsigned int ERROR_FLAG = 1;
+    static const unsigned int FINALIZE_FLAG = 2;
+    typedef unsigned int HeaderType;
+
+    static HeaderType* headerPtr (void* ptr)
+    {
+      return static_cast<HeaderType*> (ptr);
+    }
+
+  public:
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+    static const int TWOSTAGE_FINALIZE_FLAG = 1 << 30;
+#endif
+    class BufferInfo {
+      unsigned int start_; // points to beginning of DATA
+      unsigned int size_;  // current size of BUFFER (max data size)
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+      int rank_;
+#endif
+    public:
+      unsigned int readDataSize (BufferType buffer) const
+      {
+	// SIZE is stored before DATA
+	return headerPtr (buffer + start_) [-1];
+      }
+      void writeDataSize (BufferType buffer, unsigned int size)
+      {
+	headerPtr (buffer + start_) [-1] = size;
+      }
+      unsigned int start () const { return start_; }
+      void setStart (unsigned int start) { start_ = start; }
+      unsigned int size () const { return size_; }
+      void setSize (unsigned int size) { size_ = size; }
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+      int rank () const { return rank_; }
+      void setRank (int rank) { rank_ = rank; }
+#endif
+    };
+
+    typedef std::vector<BufferInfo> BufferInfos;
+    typedef std::vector<BufferInfo*> BufferInfoPtrs;
+  private:
+
+  public:
+    class Block {
+    private:
+      int rank_;
+      unsigned int start_; // points to ERRORFLAG
+      unsigned int size_;  // includes ERRORFLAG and buffer SIZEs
+      BufferInfoPtrs bufferInfoPtr_;
+    public:
+      int rank () const { return rank_; }
+      void setRank (int rank) { rank_ = rank; }
+      unsigned int start () const { return start_; }
+      void setStart (unsigned int start) { start_ = start; }
+      unsigned int size () const { return size_; }
+      void setSize (unsigned int size) { size_ = size; }
+      unsigned int nBuffers () const { return bufferInfoPtr_.size (); }
+      unsigned int headerSize () const
+      {
+	return sizeof (HeaderType) * (1 + nBuffers ());
+      }
+      bool errorFlag (BufferType buffer) const
+      {
+	//*fixme* Can set start_ to proper offset
+	unsigned int offset = rank_ == MPI::COMM_WORLD.Get_rank () ? 0 : start_;
+	return *headerPtr (buffer + offset) & MultiBuffer::ERROR_FLAG;
+      }
+      void clearBufferFlags (BufferType buffer)
+      {
+	*headerPtr (buffer + start_) = 0;
+      }
+      void clearBufferErrorFlag (BufferType buffer)
+      {
+	*headerPtr (buffer + start_) &= ~MultiBuffer::ERROR_FLAG;
+      }
+      bool finalizeFlag (BufferType buffer) const
+      {
+	return *headerPtr (buffer + start_) & MultiBuffer::FINALIZE_FLAG;
+      }
+      void setFinalizeFlag (BufferType buffer)
+      {
+	*headerPtr (buffer + start_) |= MultiBuffer::FINALIZE_FLAG;
+      }
+      unsigned int requestedDataSize (BufferType buffer, int i) const
+      {
+	unsigned int offset = rank_ == MPI::COMM_WORLD.Get_rank () ? 0 : start_;
+	return headerPtr (buffer + offset)[1 + i];
+      }
+      BufferInfoPtrs::iterator begin () { return bufferInfoPtr_.begin (); }
+      BufferInfoPtrs::iterator end () { return bufferInfoPtr_.end (); }
+      BufferInfoPtrs::reverse_iterator rbegin ()
+      {
+	return bufferInfoPtr_.rbegin ();
+      }
+      BufferInfoPtrs::reverse_iterator rend ()
+      {
+	return bufferInfoPtr_.rend ();
+      }
+      void push_back (BufferInfo* bi) { bufferInfoPtr_.push_back (bi); }
+    };
+
+  private:
+    // allocated by realloc in order to use a minimal amount of memory at resize
+    BufferType buffer_;
+    unsigned int size_;
+    unsigned int errorBlockSize_;
+    int localLeader_;
+
+  public:
+    typedef std::vector<Block> Blocks;
+  private:
+    Blocks block_;
+
+  public:
+    class InputSubconnectorInfo {
+      InputSubconnector* subconnector_;
+      BufferInfos bufferInfo_;
+    public:
+      InputSubconnectorInfo (InputSubconnector* s) : subconnector_ (s) { }
+      InputSubconnector* subconnector () const { return subconnector_; }
+      void setSize (unsigned int size) { bufferInfo_.resize (size); }
+      BufferInfos::iterator begin () { return bufferInfo_.begin (); }
+      BufferInfos::iterator end () { return bufferInfo_.end (); }
+    };
+
+    class OutputSubconnectorInfo {
+      OutputSubconnector* subconnector_;
+      BufferInfo* bufferInfo_;
+    public:
+      OutputSubconnectorInfo (OutputSubconnector* s, BufferInfo* bi)
+	: subconnector_ (s), bufferInfo_ (bi) { }
+      OutputSubconnector* subconnector () const { return subconnector_; }
+      BufferInfo* bufferInfo () const { return bufferInfo_; }
+    };
+
+  private:
+    //typedef std::vector<InputSubconnectorInfo> InputSubconnectorInfos;
+    //InputSubconnectorInfos inputSubconnectorInfo_;
+    typedef std::map<Connector*, OutputSubconnectorInfo> OutputConnectorMap;
+    OutputConnectorMap outputConnectorMap_;
+
+    typedef std::map<Connector*, InputSubconnectorInfo> InputConnectorMap;
+    InputConnectorMap inputConnectorMap_;
+
+    GroupMap groupMap_;
+
+    std::vector<Updateable*> multiConnectors;
+
+  public:
+    BufferType buffer () const { return buffer_; }
+
+  private:
+    void setupRankMap (int, RankMap* rankMap);
+    void registerGroup (unsigned int leader, std::vector<int>& worldRanks);
+    unsigned int computeSize (bool twostage);
+
+  public:
+    MultiBuffer (MPI::Intracomm comm,
+		 int leader,
+		 std::vector<Connector*>& connectors);
+
+    Intervals& getWorldRankIntervals (int leader) { return groupMap_[leader]; }
+
+    void addMultiConnector (Updateable* multiConnector)
+    {
+      multiConnectors.push_back (multiConnector);
+    }
+
+    Blocks::iterator getBlock (int rank);
+    Blocks::iterator blockEnd () { return block_.end (); }
+    void dumpBlocks ();
+
+    int localLeader () const { return localLeader_; }
+
+    InputSubconnectorInfo* getInputSubconnectorInfo (Connector* connector);
+
+    OutputSubconnectorInfo* getOutputSubconnectorInfo (Connector* connector);
+
+    void clearFlags ()
+    {
+      headerPtr (buffer_)[0] = 0;
+    }
+
+    void clearErrorFlag ()
+    {
+      headerPtr (buffer_)[0] &= ~MultiBuffer::ERROR_FLAG;
+    }
+
+    void setErrorFlag ()
+    {
+      headerPtr (buffer_)[0] |= MultiBuffer::ERROR_FLAG;
+    }
+
+    void writeRequestedDataSize (int i, unsigned int size)
+    {
+      headerPtr (buffer_)[1 + i] = size;
+    }
+
+    void restructure (bool twostage);
+  };
+
+
+  class MultiConnector : public Updateable {
+  private:
+    MultiBuffer* multiBuffer_;
+    MultiBuffer::BufferType buffer_;
+    int connectorCode_;
+    std::vector<std::pair<int, int> > connectorIds_;
+
+    typedef MultiBuffer::Intervals Intervals;
+
+    struct MCGroupInfo {
+      Intervals* worldRankIntervals;
+      unsigned int size;
+      bool blank;
+    };
+
+    typedef MultiBuffer::Block Block;
+    typedef MultiBuffer::Blocks Blocks;
+    typedef std::vector<Block*> BlockPtrs;
+    BlockPtrs block_;
+
+    typedef MultiBuffer::BufferInfo BufferInfo;
+    typedef MultiBuffer::BufferInfos BufferInfos;
+    typedef MultiBuffer::BufferInfoPtrs BufferInfoPtrs;
+
+    typedef std::vector<MultiBuffer::OutputSubconnectorInfo*> OutputSubconnectorInfos;
+    OutputSubconnectorInfos outputSubconnectorInfo_;
+
+    typedef std::vector<MultiBuffer::InputSubconnectorInfo*> InputSubconnectorInfoPtrs;
+    InputSubconnectorInfoPtrs inputSubconnectorInfo_;
+
+    bool* blank_;
+    std::string id_; // used for debugging
+    int* recvcounts_;
+    int* displs_;
+    bool recvcountInvalid_;
+    bool restructuring_;
+    //int rank_;
+    //int nRanks_;
+    typedef std::map<unsigned int, MCGroupInfo> GroupMap;
+    GroupMap* groupMap_;
+    MPI::Group group_;
+    MPI::Intracomm comm_;
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+    static const int TWOSTAGE_FINALIZE_FLAG = MultiBuffer::TWOSTAGE_FINALIZE_FLAG;
+    bool twostage_;
+    bool doAllgather_;
+#endif
+
+    bool writeSizes ();
+    void fillBuffers ();
+    void processInput ();
+    void mergeGroup (int leader, bool isInput);
+
+    int rank () const { return comm_.Get_rank (); }
+    int size () const { return comm_.Get_size (); }
+    //void setErrorFlag (MultiBuffer::BufferType buffer);
+#ifdef MUSIC_TWOSTAGE_ALLGATHER
+    void processReceived ();
+    void checkRestructure ();
+#endif
+
+  public:
+    //MultiConnector () { }
+    MultiConnector (MultiBuffer* multiBuffer);
+    MultiConnector (MultiBuffer* multiBuffer,
+		    std::vector<Connector*>& connectors);
+    int connectorCode () const { return connectorCode_; }
+    void add (Connector* connector);
+    void initialize ();
+    void tick ();
+    bool isFinalized ();
+    void finalize ();
+    void update ();
+  };
+
+}
+
+#endif // MUSIC_USE_MPI
+
+#define MUSIC_MULTIBUFFER_HH
+#endif
diff --git a/src/music/music-config.hh.in b/src/music/music-config.hh.in
new file mode 100644
index 0000000..6a5cc72
--- /dev/null
+++ b/src/music/music-config.hh.in
@@ -0,0 +1,32 @@
+#ifndef MUSIC_CONFIG_HH
+
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define MUSIC_HAVE_SIZE_T @MUSIC_HAVE_SIZE_T@
+#define MUSIC_HAVE_LONG_LONG @MUSIC_HAVE_LONG_LONG@
+#define MUSIC_USE_MPI @MUSIC_USE_MPI@
+#define MUSIC_ISENDWAITALL @MUSIC_ISENDWAITALL@
+#define MUSIC_ANYSOURCE @MUSIC_ANYSOURCE@
+
+#if MUSIC_USE_MPI
+#include <mpi.h> // Must be included first on BG/L
+#endif
+
+#define MUSIC_CONFIG_HH
+#endif /* MUSIC_CONFIG_HH */
diff --git a/src/music/ordered_ilist.hh b/src/music/ordered_ilist.hh
new file mode 100644
index 0000000..849b503
--- /dev/null
+++ b/src/music/ordered_ilist.hh
@@ -0,0 +1,259 @@
+/*
+ *  This file is distributed together with MUSIC.
+ *  Copyright (C) 2012 Mikael Djurfeldt
+ *
+ *  This interval table implementation 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; either version 3 of the License, or (at your option)
+ *  any later version.
+ *
+ *  The interval table implementation 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_ORDERED_ILIST_HH
+
+#include <vector>
+
+extern "C" {
+#include <assert.h>
+}
+
+namespace MUSIC {
+
+  template<class DataType>
+  class OrderedIList {
+    typedef int ListPtr;
+
+    static const ListPtr NILPTR = -1;
+
+  public:
+    class Interval {
+      DataType begin_;
+      DataType end_;
+    public:
+      Interval () { }
+      Interval (DataType b, DataType e) : begin_ (b), end_ (e) { }
+      DataType begin () const { return begin_; }
+      void setBegin (const DataType x) { begin_ = x; }
+      DataType end () const { return end_; }
+      void setEnd (const DataType x) { end_ = x; }
+    };
+
+  private:
+    struct Node {
+      Node (DataType b, DataType e, ListPtr n)
+	: ival_ (Interval (b, e)), next_ (n)
+      { }
+      Interval ival_; // inclusive
+      ListPtr next_;
+    };
+
+    static std::vector<Node> node_;
+    static OrderedIList freePtr_;
+
+    ListPtr lptr_;
+
+    DataType begin_ () const { return node_[lptr_].ival_.begin (); }
+    void setBegin_ (const DataType x) { node_[lptr_].ival_.setBegin (x); }
+    DataType end_ () const { return node_[lptr_].ival_.end (); }
+    void setEnd_ (const DataType x) { node_[lptr_].ival_.setEnd (x); }
+    OrderedIList next_ () const { return OrderedIList (node_[lptr_].next_); }
+    void setNext_ (const OrderedIList list) const { node_[lptr_].next_ = list.lptr_; }
+    OrderedIList cons (const DataType b, const DataType e, const OrderedIList n);
+    void free (const OrderedIList list);
+  public:
+    static const OrderedIList NIL;
+
+    class iterator {
+      ListPtr lptr_;
+      OrderedIList list () const { return OrderedIList (lptr_); }
+    public:
+      iterator (OrderedIList list) : lptr_ (list.lptr_) { }
+      bool operator!= (const iterator& i) const
+      {
+	return lptr_ != i.lptr_;
+      }
+      iterator& operator++ () { lptr_ = list ().next_ ().lptr_; return *this; }
+      const Interval& operator* () const
+      {
+	return node_[lptr_].ival_;
+      }
+      const Interval* operator-> () const
+      {
+	return &node_[lptr_].ival_;
+      }
+    };
+
+    OrderedIList () : lptr_ (NILPTR) { }
+    OrderedIList (ListPtr ptr) : lptr_ (ptr) { }
+    bool operator== (const OrderedIList& list) const { return lptr_ == list.lptr_; }
+    bool operator!= (const OrderedIList& list) const { return lptr_ != list.lptr_; }
+    bool isEmpty () const { return lptr_ == NILPTR; }
+    OrderedIList insert (DataType i) { return insert (i, *this); }
+    OrderedIList insert (DataType i, OrderedIList hint);
+    iterator begin () const { return iterator (*this); }
+    iterator end () const { return iterator (NIL); }
+    unsigned int size () const;
+
+    static unsigned int nNodes () { return node_.size (); }
+    static void trimNodes () { std::vector<Node> (node_).swap (node_); }
+    static void reset () { freePtr_ = NIL; node_.clear (); trimNodes (); }
+
+#ifdef MUSIC_DEBUG
+    static OrderedIList freeList () { return freePtr_; }
+#endif
+  };
+
+  template<class DataType>
+  std::vector<typename OrderedIList<DataType>::Node> OrderedIList<DataType>::node_;
+
+  template<class DataType>
+  OrderedIList<DataType> OrderedIList<DataType>::freePtr_
+  = OrderedIList<DataType>::NIL;
+
+  template<class DataType>
+  const OrderedIList<DataType> OrderedIList<DataType>::NIL;
+
+  template<class DataType>
+  OrderedIList<DataType>
+  OrderedIList<DataType>::cons (const DataType b,
+				const DataType e,
+				const OrderedIList n)
+  {
+    if (freePtr_.isEmpty ())
+      {
+	// create a new node
+	ListPtr lptr = node_.size ();
+	node_.push_back (Node (b, e, n.lptr_));
+	return OrderedIList (lptr);
+      }
+    else
+      {
+	// unlink from freelist
+	OrderedIList list = freePtr_;
+	freePtr_ = freePtr_.next_ ();
+	list.setBegin_ (b);
+	list.setEnd_ (e);
+	list.setNext_ (n);
+	return list;
+      }
+  }
+
+  template<class DataType>
+  void
+  OrderedIList<DataType>::free (const OrderedIList list)
+  {
+    list.setNext_ (freePtr_);
+    freePtr_ = list;
+  }
+
+  template<class DataType>
+  OrderedIList<DataType>
+  OrderedIList<DataType>::insert (DataType i, OrderedIList hint)
+  {
+    if (hint.isEmpty ())
+      {
+	if (isEmpty ())
+	  return *this = cons (i, i, NIL);
+	if (i < begin_ ())
+	  {
+	    if (i + 1 == begin_ ())
+	      setBegin_ (i);
+	    else
+	      *this = cons (i, i, *this);
+	    return *this;
+	  }
+	OrderedIList list = *this;
+	while (true)
+	  {
+	    OrderedIList next = list.next_ ();
+	    assert (i > list.end_ ());
+	    if (next.isEmpty ())
+	      {
+		if (i == list.end_ () + 1)
+		  {
+		    list.setEnd_ (i);
+		    return list;
+		  }
+	      }
+	    else
+	      {
+		if (i == list.end_ () + 1)
+		  {
+		    if (i + 1 == next.begin_ ())
+		      {
+			list.setEnd_ (next.end_ ());
+			list.setNext_ (next.next_ ());
+			free (next);
+		      }
+		    else
+		      {
+			list.setEnd_ (i);
+		      }
+		    return list;
+		  }
+	      }
+	    if (next.isEmpty ())
+	      {
+		next = cons (i, i, NIL);
+		list.setNext_ (next);
+		return next;
+	      }
+	    if (i < next.begin_ ())
+	      {
+		if (i + 1 == next.begin_ ())
+		  next.setBegin_ (i);
+		else
+		  {
+		    next = cons (i, i, next);
+		    list.setNext_ (next);
+		  }
+		return next;
+	      }
+	    list = next;
+	  }
+      }
+    else
+      {
+	if (i < hint.begin_ () || !hint.next_ ().isEmpty ())
+	  return insert (i, NIL);
+	assert (i > end_ ());
+	if (i == hint.end_ () + 1)
+	  {
+	    hint.setEnd_ (i);
+	    return hint;
+	  }
+	else
+	  {
+	    OrderedIList next = cons (i, i, NIL);
+	    hint.setNext_ (next);
+	    return next;
+	  }
+      }
+  }
+
+  template<class DataType>
+  unsigned int
+  OrderedIList<DataType>::size () const
+  {
+    unsigned int size = 0;
+    OrderedIList list = *this;
+    while (!list.isEmpty ())
+      {
+	++size;
+	list = list.next_ ();
+      }
+    return size;
+  }
+
+}
+
+#define MUSIC_ORDERED_ILIST_HH
+#endif // MUSIC_ORDERED_ILIST_HH
diff --git a/src/music/parse.hh b/src/music/parse.hh
new file mode 100644
index 0000000..ac8e276
--- /dev/null
+++ b/src/music/parse.hh
@@ -0,0 +1,41 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_PARSE_HH
+#include <string>
+#include <vector>
+#include <istream>
+namespace MUSIC {
+  
+  class Parser {
+    std::istream* in;
+    void parseString (std::ostringstream& arg, char delim);
+  public:
+    Parser (std::string s);
+    ~Parser();
+    bool eof () { return in->eof (); }
+    void ignoreWhitespace ();
+    std::string nextArg ();
+  };
+
+  char ** parseArgs (std::string cmd,
+		     std::string args,
+		     int* argc);
+}
+#define MUSIC_PARSE_HH
+#endif
diff --git a/src/music/permutation_index.hh b/src/music/permutation_index.hh
new file mode 100644
index 0000000..5d1ee95
--- /dev/null
+++ b/src/music/permutation_index.hh
@@ -0,0 +1,59 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_PERMUTATION_INDEX_HH
+#include <vector>
+#include "music/index_map.hh"
+
+namespace MUSIC {
+
+  /*
+   * This index map is part of the MUSIC API and documented
+   * in section 4.3.8 of the MUSIC manual.
+   */
+
+  class PermutationIndex : public IndexMap {
+    std::vector<IndexInterval> indices_;
+  public:
+    class iterator : public IndexMap::IteratorImplementation {
+      const IndexInterval* intervalPtr;
+    public:
+      iterator (const IndexInterval* ptr) : intervalPtr (ptr) { }
+      virtual const IndexInterval operator* () { return *intervalPtr; }
+      virtual const IndexInterval* dereference () { return intervalPtr; }
+      virtual bool isEqual (IteratorImplementation* i) const
+      {
+	return intervalPtr == static_cast<iterator*> (i)->intervalPtr;
+      }
+      virtual void operator++ () { ++intervalPtr; }
+      virtual IteratorImplementation* copy ()
+      {
+	return new iterator (intervalPtr);
+      }
+    };
+    
+    PermutationIndex (GlobalIndex *indices, int size);
+    PermutationIndex (std::vector<IndexInterval>& indices);
+    virtual IndexMap::iterator begin ();
+    virtual const IndexMap::iterator end () const;
+    virtual IndexMap* copy ();    
+  };
+
+}
+#define MUSIC_PERMUTATION_INDEX_HH
+#endif
diff --git a/src/music/port.hh b/src/music/port.hh
new file mode 100644
index 0000000..9f2d50f
--- /dev/null
+++ b/src/music/port.hh
@@ -0,0 +1,285 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_PORT_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include <mpi.h>
+
+#include <string>
+
+#include <music/data_map.hh>
+#include <music/index_map.hh>
+#include <music/event.hh>
+#include <music/message.hh>
+#include <music/connector.hh>
+#include <music/sampler.hh>
+#include <music/event_routing_map.hh>
+#include <music/connectivity.hh>
+#include <music/spatial.hh>
+
+namespace MUSIC {
+
+  class Setup;
+/* remedius
+ * 1. Since one more type of Connector was added - CollectiveConnector,
+ * to avoid branching of different Connector return types,
+ * all makeOutputConnector, makeInputConnector methods were replaced with
+ * Connector* makeConnector method and placed to the base class Port.
+ * 2. RedistributionPort by its definition didn't fit the current meaning
+ * for Input/Output ports anymore, hence it was removed.
+ * All the functionality from Input/OutputRedistributionPort
+ * has been moved to Input/OutputPort respectively.
+ */
+  class Port {
+  public:
+    Port () { }
+    Port (Setup* s, std::string identifier);
+
+    virtual void buildTable () { };
+    virtual void setupCleanup () { };
+    bool isConnected ();
+    bool hasWidth ();
+    int width ();
+    void checkIndexMap (IndexMap* indexMap);
+
+  protected:
+    IndexMap* indices_;
+    Index::Type index_type_;
+    std::string portName_;
+    Setup* setup_;
+    ConnectivityInfo* ConnectivityInfo_;
+    virtual Connector* makeConnector (ConnectorInfo connInfo) = 0;
+    void assertOutput ();
+    void assertInput ();
+
+  public: // MDJ 2012-08-07 public for now---see comment in runtime.cc
+    virtual ~Port(){};
+
+  private:
+
+    void checkConnected (std::string action);
+    bool isMapped_;
+    friend class Runtime;
+  };
+
+
+  // A ticking port is a port which needs to be updated at every tick ()
+
+  class TickingPort : public virtual Port {
+  public:
+    virtual void tick () = 0;
+  };
+
+
+  class OutputPort :  public  virtual Port {
+  protected:
+	OutputPort () { }
+    virtual void mapImpl (IndexMap* indices,
+			  Index::Type type,
+			  int maxBuffered,
+			  int dataSize);
+    friend class Implementer;
+  };
+
+  class InputPort :   public  virtual Port {
+  protected:
+    InputPort (){ }
+    void mapImpl (IndexMap* indices,
+		  Index::Type type,
+		  double accLatency,
+		  int maxBuffered,
+		  bool interpolate);
+    friend class Implementer;
+  };
+
+  class ContPort :  public virtual Port {
+  protected:
+    Sampler sampler;
+    MPI::Datatype type_;
+  };
+
+  class ContOutputPort : public ContPort,
+			 public OutputPort,
+			 public TickingPort {
+    void mapImpl (DataMap* indices, int maxBuffered);
+    Connector* makeConnector (ConnectorInfo connInfo);
+    friend class Implementer;
+
+  public:
+    ContOutputPort (Setup* s, std::string id)
+      : Port (s, id) { }
+    void map (DataMap* dmap);
+    void map (DataMap* dmap, int maxBuffered);
+    void tick ();
+  };
+  
+  class ContInputPort : public ContPort, public InputPort {
+    double delay_;
+    void mapImpl (DataMap* dmap,
+		  double delay,
+		  int maxBuffered,
+		  bool interpolate);
+    Connector* makeConnector (ConnectorInfo connInfo);
+    friend class Implementer;
+
+  public:
+    ContInputPort (Setup* s, std::string id)
+      : Port (s, id) { }
+    void map (DataMap* dmap, double delay = 0.0, bool interpolate = true);
+    void map (DataMap* dmap, int maxBuffered, bool interpolate = true);
+    void map (DataMap* dmap,
+	      double delay,
+	      int maxBuffered,
+	      bool interpolate = true);
+  };
+
+
+
+  /* remedius
+   * EventOutputPort constructor, makeOutputConnector() and buildTable() methods were hided from the user.
+   * In order to give the Setup class access to EventOutputPort constructor,
+   * Setup class was declared as a friend class to EventOutputPort.
+   */
+  class EventOutputPort :  public OutputPort {
+	EventRouter *router;
+    EventRoutingMap<FIBO*>* routingMap;
+  public:
+    void map (IndexMap* indices, Index::Type type);
+    void map (IndexMap* indices, Index::Type type, int maxBuffered);
+    void insertEvent (double t, GlobalIndex id);
+    void insertEvent (double t, LocalIndex id);
+    EventOutputPort (Setup* s, std::string id);
+
+    void mapImpl (IndexMap* indices,
+		  Index::Type type,
+		  int maxBuffered);
+    void insertEventImpl (double t, int id);
+
+  private:
+    void setupCleanup () { };
+  public: // MDJ 2012-08-07 public for now---see comment in runtime.cc
+    ~EventOutputPort();
+
+  private:
+    Connector* makeConnector (ConnectorInfo connInfo);
+    void buildTable ();
+    friend class Setup;
+    friend class Implementer;
+  };
+/* remedius
+ * EventInputPort constructor was hided from the user.
+ * In order to give the Setup class access to EventInputPort constructor,
+ * Setup class was declared as a friend class to EventInputPort.
+ * routingMap field and  buildTable() method were added to EventInputPort class since
+ * the routing of the data can also happen on the input side (collective algorithm).
+ */
+  class EventInputPort : public InputPort {
+  private:
+	Index::Type type_;
+    EventHandlerPtr handleEvent_;
+   // EventRoutingMap<EventHandlerGlobalIndex*>* routingMap;
+  public:
+    void map (IndexMap* indices,
+	      EventHandlerGlobalIndex* handleEvent,
+	      double accLatency = 0.0);
+    void map (IndexMap* indices,
+	      EventHandlerLocalIndex* handleEvent,
+	      double accLatency = 0.0);
+    void map (IndexMap* indices,
+	      EventHandlerGlobalIndex* handleEvent,
+	      double accLatency,
+	      int maxBuffered);
+    void map (IndexMap* indices,
+	      EventHandlerLocalIndex* handleEvent,
+	      double accLatency,
+	      int maxBuffered);
+    EventInputPort (Setup* s, std::string id);
+  protected:
+    void mapImpl (IndexMap* indices,
+		  Index::Type type,
+		  EventHandlerPtr handleEvent,
+		  double accLatency,
+		  int maxBuffered);
+
+    Connector* makeConnector (ConnectorInfo connInfo);
+    // Facilities to support the C interface
+  public:
+    EventHandlerGlobalIndexProxy*
+    allocEventHandlerGlobalIndexProxy (void (*) (double, int));
+    EventHandlerLocalIndexProxy*
+    allocEventHandlerLocalIndexProxy (void (*) (double, int));
+  private:
+    EventHandlerGlobalIndexProxy cEventHandlerGlobalIndex;
+    EventHandlerLocalIndexProxy cEventHandlerLocalIndex;
+
+    friend class Setup;
+    friend class Implementer;
+  };
+
+
+  class MessagePort : public virtual Port {
+  protected:
+    int rank_;
+  public:
+    MessagePort (Setup* s);
+  };
+
+  class MessageOutputPort : public MessagePort,
+			    public OutputPort {
+    std::vector<FIBO*> buffers;
+  public:
+    MessageOutputPort (Setup* s, std::string id);
+    void map ();
+    void map (int maxBuffered);
+    void insertMessage (double t, void* msg, size_t size);
+  protected:
+    void mapImpl (int maxBuffered);
+    Connector* makeConnector (ConnectorInfo connInfo);
+    friend class Implementer;
+  };
+
+  class MessageInputPort : public MessagePort,
+			   public InputPort {
+    MessageHandler* handleMessage_;
+  public:
+    MessageInputPort (Setup* s, std::string id);
+    void map (MessageHandler* handler = 0, double accLatency = 0.0);
+    void map (int maxBuffered);
+    void map (double accLatency, int maxBuffered);
+    void map (MessageHandler* handler, int maxBuffered);
+    void map (MessageHandler* handler, double accLatency, int maxBuffered);
+  protected:
+    void mapImpl (MessageHandler* handleEvent,
+		  double accLatency,
+		  int maxBuffered);
+    Connector* makeConnector (ConnectorInfo connInfo);
+    friend class Implementer;
+
+  public:
+    MessageHandlerProxy*
+    allocMessageHandlerProxy (void (*) (double, void*, size_t));
+  private:
+    MessageHandlerProxy cMessageHandler;
+  };
+
+
+}
+#endif
+#define MUSIC_PORT_HH
+#endif
diff --git a/src/music/predict_rank-c.h b/src/music/predict_rank-c.h
new file mode 100644
index 0000000..00654f6
--- /dev/null
+++ b/src/music/predict_rank-c.h
@@ -0,0 +1,24 @@
+#ifndef PREDICT_RANK_C_H
+
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2011 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+int MUSIC_predictRank (int argc, char **argv);
+
+#define PREDICT_RANK_C_H
+#endif /* PREDICT_RANK_C_H */
diff --git a/src/music/predict_rank.hh b/src/music/predict_rank.hh
new file mode 100644
index 0000000..7dbe921
--- /dev/null
+++ b/src/music/predict_rank.hh
@@ -0,0 +1,28 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2011 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PREDICT_RANK_HH
+
+namespace MUSIC {
+
+  int predictRank (int argc, char** argv);
+
+}
+
+#define PREDICT_RANK_HH
+#endif
diff --git a/src/music/runtime.hh b/src/music/runtime.hh
new file mode 100644
index 0000000..a7417ee
--- /dev/null
+++ b/src/music/runtime.hh
@@ -0,0 +1,99 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_RUNTIME_HH
+//#define MUSIC_DEBUG
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include <mpi.h>
+#include <vector>
+
+#include "music/setup.hh"
+#include "music/port.hh"
+#include "music/clock.hh"
+#include "music/connector.hh"
+#include "music/scheduler.hh"
+#include "music/scheduler_agent.hh"
+namespace MUSIC
+{
+
+  /*
+   * This is the Runtime object in the MUSIC API
+   *
+   * It is documented in section 4.4 of the MUSIC manual
+   */
+
+  class Runtime
+  {
+  public:
+    Runtime (Setup* s, double h);
+    ~Runtime ();
+
+    MPI::Intracomm
+    communicator ();
+
+    void
+    finalize ();
+    void
+    tick ();
+    double
+    time ();
+
+  private:
+    Clock localTime;
+    //Clock nextComm;
+    std::string app_name;
+    int leader_;
+    std::vector<std::pair<double, Connector *> > schedule;
+    MPI::Intracomm comm;
+    std::vector<Port*> ports;
+    std::vector<TickingPort*> tickingPorts;
+    std::vector<Connector*> connectors;
+    std::vector<PostCommunicationConnector*> postCommunication;
+    std::vector<PreCommunicationConnector*> preCommunication;
+    Scheduler *scheduler;
+    std::vector<SchedulerAgent*> sAgents;
+    MulticommAgent* mAgent;
+    static bool isInstantiated_;
+
+    typedef std::vector<Connection*> Connections;
+    bool needsMultiCommunication ();
+    void
+    takeTickingPorts (Setup* s);
+    void
+    connectToPeers (Connections* connections);
+    void
+    specializeConnectors (Connections* connections);
+    void
+    spatialNegotiation ();
+    void
+    takePreCommunicators ();
+    void
+    takePostCommunicators ();
+    void
+    buildTables (Setup* s);
+    void
+    temporalNegotiation (Setup* s, Connections* connections);
+    void
+    initialize (Setup* s);
+  };
+
+}
+#endif
+#define MUSIC_RUNTIME_HH
+#endif
diff --git a/src/music/sampler.hh b/src/music/sampler.hh
new file mode 100644
index 0000000..31e026a
--- /dev/null
+++ b/src/music/sampler.hh
@@ -0,0 +1,67 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// NOTE: rename to Interpolator?
+
+#ifndef MUSIC_SAMPLER_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include <music/data_map.hh>
+
+namespace MUSIC {
+
+  class Sampler {
+    DataMap* dataMap_;
+    DataMap* interpolationDataMap_;
+    bool hasSampled;
+    ContDataT* prevSample_;
+    ContDataT* sample_;
+    ContDataT* interpolationData_;
+    int elementSize;
+    int size;
+  public:
+    Sampler ();
+    ~Sampler ();
+    void configure (DataMap* dataMap);
+    void initialize ();
+    DataMap* dataMap () { return dataMap_; }
+    // this class manages one single copy of the interpolation DataMap
+    DataMap* interpolationDataMap ();
+    void newSample ();
+    void sampleOnce ();
+    void sample ();
+    ContDataT* insert ();
+    void interpolate (double interpolationCoefficient);
+    void interpolateToApplication (double interpolationCoefficient);
+  private:
+    void swapBuffers (ContDataT*& b1, ContDataT*& b2);
+    void interpolateTo (DataMap* dataMap, double interpolationCoefficient);
+    void interpolate (int from,
+		      int n,
+		      double interpolationCoefficient,
+		      double* dest);
+    void interpolate (int from,
+		      int n,
+		      float interpolationCoefficient,
+		      float* dest);
+  };
+
+}
+#endif
+#define MUSIC_SAMPLER_HH
+#endif
diff --git a/src/music/scheduler.hh b/src/music/scheduler.hh
new file mode 100644
index 0000000..b068163
--- /dev/null
+++ b/src/music/scheduler.hh
@@ -0,0 +1,234 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2011, 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_SCHEDULER_HH
+
+#include "music/music-config.hh"
+
+#if MUSIC_USE_MPI
+#include <limits>
+#include <vector>
+#include <music/clock.hh>
+#include <music/connector.hh>
+#include <music/multibuffer.hh>
+#include <music/application_map.hh>
+#include <music/temporal.hh>
+namespace MUSIC
+{
+
+// The Scheduler is responsible for the timing involved in
+// communication, sampling, interpolation and buffering.
+  class SchedulerAgent;
+  class SchedulerAgent;
+  class SApplData;
+  class SConnData;
+
+  class Scheduler
+  {
+
+  public:
+
+    class SConnData;
+
+
+    class SApplData
+    {
+    public:
+      Clock localTime;
+      int leader;
+      int nProcs;
+      int color;
+    };
+
+
+    class SConnData
+    {
+    public:
+      Clock nextSend;
+      Clock nextReceive;
+      Clock sSend;
+      ConnectionDescriptor descr;
+      Connector *connector;
+      bool isLoopConnected;
+
+
+      void
+      reset ()
+      {
+        nextSend.reset ();
+        nextReceive.reset ();
+        sSend.reset ();
+        isLoopConnected = false;
+      }
+
+
+      void
+      postponeNextSend (Clock newTime)
+      {
+        sSend = nextSend;
+        nextSend = newTime;
+      }
+    };
+
+
+    typedef ANode<SApplData, SConnData> SNode;
+    typedef AEdge<SApplData, SConnData> SConnection;
+
+
+    class SGraph : public AGraph<SApplData, SConnData>
+    {
+      int tmp_color_;
+    public:
+      SGraph (int color, int nApps, int nEdges) :
+          AGraph<SApplData, SConnData> (color, nApps, nEdges), tmp_color_ (
+              color)
+      {
+      }
+      ;
+
+
+      void
+      setTempColor (int tmp_color)
+      {
+        tmp_color_ = tmp_color;
+      }
+
+
+      void handleLoop (SNode &x, std::vector<SConnection> & path);
+    };
+
+
+  private:
+    SGraph *nodes;
+    SGraph::iterator iter_node;
+    SNode::edge_iterator iter_conn;
+
+    std::vector<SchedulerAgent *> agents_;
+    std::vector<SchedulerAgent *>::iterator cur_agent_;
+
+    SConnection last_sconn_;
+
+    SApplData *appl_data_;
+    SConnData *conn_data_;
+
+    int color_;
+    int leader_;
+    MPI::Intracomm comm_;
+  public:
+
+    Scheduler (MPI::Intracomm comm, int leader);
+    ~Scheduler ();
+
+    void initialize (TemporalNegotiatorGraph *appl_graph,
+        std::vector<Connector*>& connectors);
+
+    void finalize (Clock& localTime, std::vector<Connector*>& connectors);
+
+    void reset (int self_node);
+
+#if 0
+    void createMultiConnectors (Clock localTime,
+        std::vector<Connector*>& connectors,
+        MultiBuffer* multiBuffer,
+        std::vector<MultiConnector*>& multiConnectors);
+    void createMultiConnNext (int self_node,
+        Clock& localTime,
+        std::vector<Connector*>& connectors,
+        MultiBuffer* multiBuffer,
+        std::vector<std::pair<double, Connector *> > &schedule);
+    void createMultiConnStep (int self_node,
+        Clock& localTime,
+        std::vector<Connector*>& connectors,
+        MultiBuffer* multiBuffer,
+        std::vector<MultiConnector*>& multiConnectors,
+        std::vector<bool>& multiProxies,
+        std::vector<Connector*>& cCache,
+        std::vector<std::pair<double, Connector *> > &schedule,
+        bool finalize);
+    void nextCommunication (Clock& localTime,
+        std::vector<std::pair<double, Connector *> > &schedule);
+
+#endif
+    void setAgent (SchedulerAgent* agent);
+
+    void initializeAgentState ();
+
+    AEdge<Scheduler::SApplData, Scheduler::SConnData>
+    pushForward ();
+
+    void tick (Clock& localTime);
+
+    bool
+    isLocalConnection (SConnection &edge)
+    {
+
+      return &edge.pre () == &nodes->at (color_)
+          || &edge.post () == &nodes->at (color_);
+
+    }
+
+    unsigned int
+    nApplications ()
+    {
+      return nodes->nNodes ();
+    }
+
+    int
+    self_node ()
+    {
+      return color_;
+    }
+
+    SConnection &
+    getLastSConnection ()
+    {
+      return last_sconn_;
+    }
+
+    int
+    getLeader ()
+    {
+      return leader_;
+    }
+
+    MPI::Intracomm
+    comm ()
+    {
+      return comm_;
+    }
+  private:
+
+    void reset ();
+
+    void setApplications (TemporalNegotiatorGraph *appl_graph);
+
+    void setConnections (TemporalNegotiatorGraph *appl_graph,
+        std::vector<Connector*>& connectors);
+
+    Clock nextApplicationReceive (SNode &node);
+
+    void advanceConnection (SConnData &data);
+
+    void advanceConnectionClocks (SConnData &data);
+  };
+
+}
+#endif
+
+#define MUSIC_SCHEDULER_HH
+#endif
diff --git a/src/music/scheduler_agent.hh b/src/music/scheduler_agent.hh
new file mode 100644
index 0000000..86060e9
--- /dev/null
+++ b/src/music/scheduler_agent.hh
@@ -0,0 +1,294 @@
+#ifndef MUSIC_SCHEDULER_AGENT_HH
+
+#include "music/music-config.hh"
+#include "music/scheduler.hh"
+#include "music/multibuffer.hh"
+#if MUSIC_USE_MPI
+
+namespace MUSIC
+{
+  class Scheduler;
+  typedef std::pair<Scheduler::SConnection, Scheduler::SConnData> SConnectionP;
+  typedef std::vector< SConnectionP > SConnectionPV;
+
+
+  class SchedulerAgent
+  {
+  protected:
+    Scheduler *scheduler_;
+    SchedulerAgent (Scheduler *scheduler);
+
+
+    class CommObject
+    {
+    public:
+      CommObject ()
+      {
+        time.set(ClockState(-1.0));
+      }
+      ;
+
+
+      CommObject (Clock time_) :
+        time (time_)
+      {
+      }
+      ;
+
+
+      virtual
+      ~CommObject ()
+      {
+      }
+
+
+      Clock time;
+
+
+      void
+      reset ()
+      {
+        time.set(ClockState(-1.0));
+      }
+
+
+      bool
+      empty ()
+      {
+        return time.integerTime() < 0;
+      }
+    };
+
+
+    virtual bool
+    fillSchedule () = 0;
+
+  public:
+    virtual
+    ~SchedulerAgent ()
+    {
+    }
+    ;
+
+
+    virtual void
+    initialize (std::vector<Connector*>& connectors)=0;
+
+
+    virtual bool
+    tick (Clock& localTime)=0;
+
+#if 0
+    virtual void
+    preFinalize (std::set<int> &cnn_ports)
+    {
+    }
+    ;
+#endif
+
+    virtual void
+    finalize (std::set<int> &cnn_ports) = 0;
+  };
+
+
+  class MulticommAgent : public virtual SchedulerAgent
+  {
+    static const int N_PLANNING_CYCLES = 100;
+
+    std::map<int, Clock> commTimes;
+    int rNodes;
+    Clock time_;
+    MultiBuffer* multiBuffer_;
+    std::vector<MultiConnector*> multiConnectors;
+
+
+    class Filter1
+    {
+      MulticommAgent &multCommObj_;
+    public:
+
+      Filter1 (MulticommAgent &multCommObj);
+
+      bool
+      operator() (SConnectionP &conn);
+    };
+
+
+    class Filter2
+    {
+      MulticommAgent &multCommObj_;
+
+    public:
+      Filter2 (MulticommAgent &multCommObj);
+
+      bool
+      operator() (SConnectionP &conn);
+    };
+
+
+    class MultiCommObject : public CommObject
+    {
+    private:
+      unsigned int multiId_;
+      unsigned int proxyId_;
+
+    public:
+      MultiCommObject (Clock time_, unsigned int multiId, unsigned int proxyId) :
+          CommObject (time_), multiId_ (multiId), proxyId_ (proxyId)
+      {
+      }
+      ;
+
+      unsigned int
+      multiId () const
+      {
+        return multiId_;
+      }
+
+
+      unsigned int
+      proxyId () const
+      {
+        return proxyId_;
+      }
+    };
+
+
+    std::vector<MultiCommObject> schedule;
+
+  public:
+
+    MulticommAgent (Scheduler *scheduler);
+
+    ~MulticommAgent ();
+
+    void initialize (std::vector<Connector*>& connectors);
+
+#if 0
+    void
+    createMultiConnectors (Clock& localTime, MPI::Intracomm comm, int leader,
+        std::vector<Connector*>& connectors);
+
+
+    bool create (Clock& localTime);
+#endif
+
+    bool tick (Clock& localTime);
+
+#if 0
+    void preFinalize (std::set<int> &cnn_ports);
+#endif
+    void finalize (std::set<int> &cnn_ports);
+
+  private:
+    std::vector<bool>* multiProxies;
+
+    std::vector<Connector*>
+    connectorsFromMultiId (unsigned int multiId);
+
+    bool
+    fillSchedule ();
+
+    void
+    NextMultiConnection (SConnectionPV &candidates);
+
+    void
+    scheduleMulticonn (Clock &time, SConnectionPV::iterator first,
+        SConnectionPV::iterator last);
+
+    friend class Filter1;
+    friend class Filter2;
+    Filter1 *filter1;
+    Filter2 *filter2;
+  };
+
+
+  class UnicommAgent : public virtual SchedulerAgent
+  {
+    class UniCommObject : public CommObject
+    {
+    public:
+      Connector *connector;
+      UniCommObject () :
+          CommObject ()
+      {
+      }
+      ;
+
+
+      UniCommObject (Clock time_, Connector *connector_) :
+          CommObject (time_), connector (connector_)
+      {
+      }
+      ;
+    };
+
+
+    UniCommObject schedule;
+
+    bool
+    fillSchedule ();
+
+  public:
+    UnicommAgent (Scheduler *scheduler);
+
+    ~UnicommAgent ()
+    {
+    }
+    ;
+
+
+    void
+    initialize (std::vector<Connector*>& connectors)
+    {
+    }
+    ;
+
+    bool
+    tick (Clock& localTime);
+
+    void
+    finalize (std::set<int> &cnn_ports);
+  };
+
+
+  class DummyAgent : public SchedulerAgent
+  {
+
+  protected:
+    bool
+    fillSchedule ()
+    {
+      return true;
+    }
+
+  public:
+    DummyAgent (Scheduler* scheduler) :
+        SchedulerAgent (scheduler)
+    {
+    }
+
+
+    void
+    initialize (std::vector<Connector*>& connectors)
+    {
+    }
+
+
+    bool
+    tick (Clock& localTime)
+    {
+      return true;
+    }
+
+
+    void
+    finalize (std::set<int> &cnn_ports)
+    {
+    }
+  };
+}
+#endif
+
+#define MUSIC_SCHEDULER_AGENT_HH
+#endif
diff --git a/src/music/setup.hh b/src/music/setup.hh
new file mode 100644
index 0000000..8fb1717
--- /dev/null
+++ b/src/music/setup.hh
@@ -0,0 +1,171 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_SETUP_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include <mpi.h>
+
+#include <string>
+#include <vector>
+
+#include <music/port.hh>
+
+#include <music/index_map.hh>
+#include <music/linear_index.hh>
+#include <music/cont_data.hh>
+#include <music/connector.hh>
+#include <music/temporal.hh>
+#include <music/configuration.hh>
+
+
+using std::string;
+
+#define MUSIC_DEFAULT_TIMEBASE 1e-9
+
+namespace MUSIC {
+
+  class Runtime;
+
+  /*
+   * This is the Setup object in the MUSIC API
+   *
+   * It is documented in section 4.3 of the MUSIC manual
+   */
+  
+  class Setup {
+    static const char* const configEnvVarName;
+    static const char* const opConfigFileName;
+    static const char* const opAppLabel;
+  public:
+    Setup (int& argc, char**& argv);
+
+    Setup (int& argc, char**& argv, int required, int* provided);
+
+    ~Setup ();
+
+    MPI::Intracomm communicator ();
+
+    bool config (string var, string* result);
+
+    bool config (string var, int* result);
+
+    bool config (string var, double* result);
+
+    ContInputPort* publishContInput (string identifier);
+
+    ContOutputPort* publishContOutput (string identifier);
+
+    EventInputPort* publishEventInput (string identifier);
+
+    EventOutputPort* publishEventOutput (string identifier);
+
+    MessageInputPort* publishMessageInput (string identifier);
+
+    MessageOutputPort* publishMessageOutput (string identifier);
+
+  private:
+    MPI::Intracomm comm;
+    Configuration* config_;
+    std::vector<Port*> ports_;
+    std::vector<Connection*>* connections_;
+    TemporalNegotiator* temporalNegotiator_;
+    double timebase_;
+    static bool isInstantiated_;
+    int& argc_;
+    char**& argv_;
+
+    bool launchedByMusic_;
+    bool postponeSetup_;
+
+    // Since we don't want to expose this internal interface to the
+    // user we put the member functions in the private part and give
+    // these classes access through a friend declaration.  Classes are
+    // still expected not to access the internal data members
+    // directly.  A cleaner solution would be to split this class into
+    // one user API part and one internal interface part.
+    friend class Runtime;
+    friend class Port;
+    friend class OutputPort;
+    friend class InputPort;
+    friend class TemporalNegotiator;
+    friend class ApplicationNode;
+    
+    double timebase () { return timebase_; }
+
+    bool launchedByMusic ();
+
+    void init (int& argc, char**& argv);
+
+    void maybeProcessMusicArgv (int& argc, char**& argv);
+
+    void maybePostponedSetup ();
+
+    void fullInit ();
+
+    ConnectivityInfo* portConnectivity (const std::string localName);
+
+    ApplicationMap* applicationMap ();
+
+    int applicationColor();
+
+    std::string applicationName();
+
+    int leader ();
+
+    int nProcs ();
+
+    ConnectivityInfo::PortDirection
+    portDirection (const std::string localName);
+
+    int portWidth (const std::string localName);
+
+    PortConnectorInfo portConnections (const std::string localName);
+
+    std::vector<Port*>* ports ()
+    {
+      return &ports_;
+    }    
+
+    void addPort (Port* p);
+    
+    std::vector<Connection*>* connections ()
+    {
+      return connections_;
+    }
+    
+    void addConnection (Connection* c);
+
+    TemporalNegotiator* temporalNegotiator () { return temporalNegotiator_; }
+    
+    void errorChecks ();
+
+    bool launchedWithExec (std::string &configStr);
+
+    bool launchedMPMD (int argc, char** argv, std::string& config);
+
+    void loadConfigFile (std::string filename, std::string &result);
+
+    bool getOption (int argc, char** argv, std::string option, std::string& result);
+
+  };
+  
+}
+#endif
+#define MUSIC_SETUP_HH
+#endif
diff --git a/src/music/spatial.hh b/src/music/spatial.hh
new file mode 100644
index 0000000..172d659
--- /dev/null
+++ b/src/music/spatial.hh
@@ -0,0 +1,195 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_NEGOTIATOR_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include <mpi.h>
+#include <vector>
+#include <memory>
+
+#include <music/index_map.hh>
+
+namespace MUSIC {
+
+  class SpatialNegotiationData {
+    IndexInterval interval_;
+    int rank_;
+    int displ_;
+  public:
+    SpatialNegotiationData () { }
+    SpatialNegotiationData (IndexInterval i, int r, int displ)
+      : interval_ (i), rank_ (r), displ_(displ) { }
+    SpatialNegotiationData (int b, int e, int l, int r, int displ)
+      : interval_ (b, e, l), rank_ (r), displ_(displ) { }
+    const IndexInterval& interval () const { return interval_; }
+    int begin () const { return interval_.begin (); }
+    int end () const { return interval_.end (); }
+    void setEnd (int e) { interval_.setEnd (e); }
+    int local () const { return interval_.local (); }
+    void setLocal (int l) { interval_.setLocal (l); }
+    void setDispl(int displ) {displ_ = displ;}
+    int rank () const { return rank_; }
+    int displ() const {return displ_; }
+  };
+
+
+  typedef std::vector<SpatialNegotiationData> NegotiationIntervals;
+  
+
+  class NegotiationIterator {
+  public:
+    class Implementation {
+    public:
+      virtual ~Implementation () { };
+      virtual bool end () = 0;
+      virtual void operator++ () = 0;
+      virtual SpatialNegotiationData* dereference () = 0;
+      virtual Implementation* copy () = 0;
+    };
+
+    class IntervalTraversal : public Implementation {
+      NegotiationIntervals& buffer;
+      unsigned int interval;
+    public:
+      IntervalTraversal (NegotiationIntervals& buffer_)
+	: buffer (buffer_), interval (0) { }
+      bool end () { return interval == buffer.size (); }
+      void operator++ () { ++interval; }
+      SpatialNegotiationData* dereference () { return &buffer[interval]; }
+      virtual Implementation* copy () { return new IntervalTraversal (*this); }
+    };
+
+    class BufferTraversal : public Implementation {
+      std::vector<NegotiationIntervals>& buffers;
+      unsigned int buffer;
+      unsigned int interval;
+      void findInterval ();
+    public:
+      BufferTraversal (std::vector<NegotiationIntervals>& buffers);
+      bool end ();
+      void operator++ ();
+      SpatialNegotiationData* dereference ();
+      virtual Implementation* copy () { return new BufferTraversal (*this); }
+    };
+
+  private:
+    Implementation* implementation_;
+    SpatialNegotiationData current_;
+    bool end_;
+  public:
+    NegotiationIterator (Implementation* impl)
+    { init (impl); }
+    NegotiationIterator (NegotiationIntervals& buffer)
+    { init (new IntervalTraversal (buffer)); }
+    NegotiationIterator (std::vector<NegotiationIntervals>& buffers)
+    { init (new BufferTraversal (buffers)); }
+    void init (Implementation* impl);
+    ~NegotiationIterator ();
+    NegotiationIterator (const NegotiationIterator& i);
+    const NegotiationIterator& operator= (const NegotiationIterator& i);
+    bool end () { return end_; }
+    NegotiationIterator& operator++ ();
+    SpatialNegotiationData* operator-> ();
+  };
+
+  class Connector;
+
+  // The SpatialNegotiator negotiates with the remote application how
+  // to redistribute data over a port pair.  This is done using the
+  // algorithm described in Djurfeldt and Ekeberg (2009) with memory
+  // complexity O (N / P) where N is the port width and P is the
+  // number of MPI processes.
+
+  class SpatialNegotiator {
+  protected:
+    MPI::Intracomm comm;
+    MPI::Intercomm intercomm;
+    IndexMap* indices;
+    Index::Type type;
+    std::vector<NegotiationIntervals> remote;
+    int width;
+    int maxLocalWidth_;
+    unsigned int localRank;
+    unsigned int nProcesses;
+    Connector* connector_; // used only for debugging
+  public:
+    SpatialNegotiator (IndexMap* indices,
+    		Index::Type type,
+    		MPI::Intracomm c);
+    virtual ~SpatialNegotiator (){};
+
+    int getWidth(){return width;}
+    int maxLocalWidth () { return maxLocalWidth_; }
+    NegotiationIterator wrapIntervals (IndexMap::iterator beg,
+				       IndexMap::iterator end,
+				       Index::Type type,
+				       int rank);
+    void send (MPI::Comm& comm, int destRank,
+	       NegotiationIntervals& intervals);
+    void receive (MPI::Comm& comm, int sourceRank,
+		  NegotiationIntervals& intervals);
+    void allToAll (std::vector<NegotiationIntervals>& out,
+		   std::vector<NegotiationIntervals>& in);
+    NegotiationIterator canonicalDistribution (int width, int nProcesses);
+    void intersectToBuffers (std::vector<NegotiationIntervals>& source,
+			     std::vector<NegotiationIntervals>& dest,
+			     std::vector<NegotiationIntervals>& buffers);
+    void intersectToBuffers (NegotiationIterator source,
+			     NegotiationIterator dest,
+			     std::vector<NegotiationIntervals>& buffers);
+  private:
+    void negotiateWidth ();
+    void intersectToBuffers2 (NegotiationIterator source,
+			      NegotiationIterator dest,
+			      std::vector<NegotiationIntervals>& buffers);
+  public:
+    virtual NegotiationIterator negotiate ( int remoteNProc, Connector* connector) = 0;
+    virtual NegotiationIterator negotiateSimple();
+  };
+
+
+  class SpatialOutputNegotiator : public SpatialNegotiator {
+    std::vector<NegotiationIntervals> local;
+    std::vector<NegotiationIntervals> results;
+  public:
+    SpatialOutputNegotiator (IndexMap* indices,
+		    Index::Type type, MPI::Intracomm c,
+		    MPI::Intercomm intercomm);
+    NegotiationIterator negotiate ( int remoteNProc,  Connector* connector);
+  private:
+    void negotiateWidth ();
+
+  };
+
+  
+  class SpatialInputNegotiator : public SpatialNegotiator {
+  public:
+    SpatialInputNegotiator (IndexMap* indices,
+		    Index::Type type, MPI::Intracomm c,
+		    MPI::Intercomm intercomm);
+    NegotiationIterator negotiate (int remoteNProc,  Connector* connector);
+  private:
+    void negotiateWidth ();
+
+  };
+
+}
+#endif
+#define MUSIC_NEGOTIATOR_HH
+#endif
diff --git a/src/music/spikes.hh b/src/music/spikes.hh
new file mode 100644
index 0000000..041d114
--- /dev/null
+++ b/src/music/spikes.hh
@@ -0,0 +1,37 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2009 CSC, KTH
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace MUSIC {
+
+  class spike {
+  public:
+    double t;
+    int id;
+  };
+
+  class spike_fifo : public fifo<spike> {
+  public:
+    void insert (int id, double t)
+    {
+      spike& s = fifo<spike>::insert ();
+      s.id = id;
+      s.t = t;
+    }
+  };    
+
+}
diff --git a/src/music/subconnector.hh b/src/music/subconnector.hh
new file mode 100644
index 0000000..5d108c7
--- /dev/null
+++ b/src/music/subconnector.hh
@@ -0,0 +1,366 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_SUBCONNECTOR_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#include <mpi.h>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+//#include <music/synchronizer.hh>
+#include <music/FIBO.hh>
+#include <music/BIFO.hh>
+#include <music/event.hh>
+#include <music/message.hh>
+
+namespace MUSIC {
+
+  // NOTE: Must be divisible by the size of the datatype of the data
+  // maps passed to cont ports
+  const int SPIKE_BUFFER_MAX = 10000 * sizeof (Event);
+  const int CONT_BUFFER_MAX = SPIKE_BUFFER_MAX; //5000 of double values per input connector
+  const int MESSAGE_BUFFER_MAX = 10000;
+
+  class EventRouter;
+
+  // The subconnector is responsible for the local side of the
+  // communication between two MPI processes, one for each port of a
+  // port pair.  It is created in connector::connect ().
+  
+  class Subconnector {
+  private:
+  protected:
+    //Synchronizer* synch;
+    MPI::Datatype type_;
+    MPI::Intercomm intercomm;
+    int remoteRank_;		// rank in inter-communicatir
+    int remoteWorldRank_;	// rank in COMM_WORLD
+    int receiverRank_;
+    int receiverPortCode_;
+    bool flushed;
+
+  public:
+    //*fixme* should not create subconnectors with uninitialized members
+    Subconnector ():type_(MPI::BYTE), flushed(false){};
+    Subconnector (MPI::Datatype type):type_ (type), flushed(false) { }
+    Subconnector (MPI::Datatype type,
+		  MPI::Intercomm intercomm,
+		  int remoteLeader,
+		  int remoteRank,
+		  int receiverRank,
+		  int receiverPortCode);
+    virtual ~Subconnector ();
+    virtual void report () { }
+    virtual void initialCommunication (double param) { }
+    virtual void maybeCommunicate () = 0;
+    virtual void maybeCommunicate (std::vector<MPI::Request> &) {};
+    virtual void flush (bool& dataStillFlowing) = 0;
+    bool isFlushed () { return flushed; }
+    int localRank () const { return intercomm.Get_rank (); }
+    int remoteRank () const { return remoteRank_; }
+    //*fixme* are the following still needed or can they be removed?
+    int remoteWorldRank () const { return remoteWorldRank_; }
+    int receiverRank () const { return receiverRank_; }
+    int receiverPortCode () const { return receiverPortCode_; }
+  };
+  
+  class OutputSubconnector : virtual public Subconnector {
+  protected:
+    OutputSubconnector () {};
+  public:
+    virtual FIBO* outputBuffer () { return NULL; }
+    // the following is part of the MultiConnector protocol
+    virtual void nextBlock () { }
+    virtual unsigned int dataSize () { return 0; }
+    virtual void setOutputBuffer (void* buffer, unsigned int size) { }
+    virtual void fillOutputBuffer () { }
+  };
+  
+  class BufferingOutputSubconnector : virtual public OutputSubconnector {
+  protected:
+    FIBO buffer_;
+  public:
+    BufferingOutputSubconnector (int elementSize);
+    FIBO* outputBuffer () { return &buffer_; }
+    void report ()
+    {
+      std::cout << "Subconnector buffer size: " << buffer_.size () << std::endl; 
+    }
+  };
+
+  class InputSubconnector : virtual public Subconnector {
+  protected:
+    InputSubconnector (){};
+  public:
+    virtual BIFO* inputBuffer () { return NULL; }
+    // the following is part of the MultiConnector protocol
+    virtual void processData (void* data, unsigned int size) { }
+  };
+
+  class ContOutputSubconnector : public BufferingOutputSubconnector{
+  protected:
+	  ContOutputSubconnector():BufferingOutputSubconnector (0){};
+  public:
+    ContOutputSubconnector (//Synchronizer* synch,
+			    MPI::Intercomm intercomm,
+			    int remoteLeader,
+			    int remoteRank,
+			    int receiverPortCode,
+			    MPI::Datatype type);
+    void initialCommunication (double param);
+    void maybeCommunicate ();
+    void send ();
+    void flush (bool& dataStillFlowing);
+  };
+  
+  class ContInputSubconnector : public InputSubconnector {
+  protected:
+    BIFO buffer_;
+    ContInputSubconnector(){};
+  public:
+    ContInputSubconnector (//Synchronizer* synch,
+			   MPI::Intercomm intercomm,
+			   int remoteLeader,
+			   int remoteRank,
+			   int receiverRank,
+			   int receiverPortCode,
+			   MPI::Datatype type);
+    BIFO* inputBuffer () { return &buffer_; }
+    void initialCommunication (double initialBufferedTicks);
+    void maybeCommunicate ();
+    void receive ();
+    void flush (bool& dataStillFlowing);
+  };
+
+  class EventSubconnector : virtual public Subconnector {
+  protected:
+    static const int FLUSH_MARK = -1;
+  };
+  
+
+
+  class EventOutputSubconnector : public BufferingOutputSubconnector,
+  				  public EventSubconnector {
+
+  protected:
+	  EventOutputSubconnector(): BufferingOutputSubconnector (sizeof (Event)){};
+    public:
+
+	  EventOutputSubconnector (//Synchronizer* synch,
+  			     MPI::Intercomm intercomm,
+  			     int remoteLeader,
+  			     int remoteRank,
+  			     int receiverPortCode);
+      void maybeCommunicate ();
+      void maybeCommunicate (std::vector<MPI::Request> &);
+
+      void send ();
+      void send (std::vector<MPI::Request> &);
+      void flush (bool& dataStillFlowing);
+
+    };
+  class EventInputSubconnector : public InputSubconnector,
+ 				 public EventSubconnector {
+   protected:
+ 	  EventInputSubconnector(){};
+   public:
+     EventInputSubconnector (//Synchronizer* synch,
+ 			    MPI::Intercomm intercomm,
+ 			    int remoteLeader,
+ 			    int remoteRank,
+ 			    int receiverRank,
+ 			    int receiverPortCode);
+ 	 void maybeCommunicate ();
+     virtual void receive () {};
+     virtual void flush (bool& dataStillFlowing);
+   };
+
+  class EventInputSubconnectorGlobal : public EventInputSubconnector {
+    EventHandlerGlobalIndex* handleEvent;
+  //  static EventHandlerGlobalIndexDummy dummyHandler;
+
+  public:
+    EventInputSubconnectorGlobal (//Synchronizer* synch,
+				  MPI::Intercomm intercomm,
+				  int remoteLeader,
+				  int remoteRank,
+				  int receiverRank,
+				  int receiverPortCode,
+				  EventHandlerGlobalIndex* eh);
+    bool receive(char *data, int size);
+    void receive ();
+  //  void flush (bool& dataStillFlowing);
+  };
+
+  class EventInputSubconnectorLocal : public EventInputSubconnector {
+    EventHandlerLocalIndex* handleEvent;
+ //   static EventHandlerLocalIndexDummy dummyHandler;
+  public:
+    EventInputSubconnectorLocal (//Synchronizer* synch,
+				 MPI::Intercomm intercomm,
+				 int remoteLeader,
+				 int remoteRank,
+				 int receiverRank,
+				 int receiverPortCode,
+				 EventHandlerLocalIndex* eh);
+    void receive ();
+  //  void flush (bool& dataStillFlowing);
+  };
+
+  class MessageSubconnector : virtual public Subconnector {
+  protected:
+    static const int FLUSH_MARK = -1;
+  };
+  
+  class MessageOutputSubconnector : public OutputSubconnector,
+				  public MessageSubconnector {
+    FIBO* buffer_;
+  public:
+    MessageOutputSubconnector (//Synchronizer* synch,
+			       MPI::Intercomm intercomm,
+			       int remoteLeader,
+			       int remoteRank,
+			       int receiverPortCode,
+			       FIBO* buffer);
+    void maybeCommunicate ();
+    void send ();
+    void flush (bool& dataStillFlowing);
+  };
+  
+  class MessageInputSubconnector : public InputSubconnector,
+				   public MessageSubconnector {
+    MessageHandler* handleMessage;
+  //  static MessageHandlerDummy dummyHandler;
+  public:
+    MessageInputSubconnector (//Synchronizer* synch,
+			      MPI::Intercomm intercomm,
+			      int remoteLeader,
+			      int remoteRank,
+			      int receiverRank,
+			      int receiverPortCode,
+			      MessageHandler* mh);
+    void maybeCommunicate ();
+    void receive ();
+    void flush (bool& dataStillFlowing);
+  };
+
+  /* remedius
+   * CollectiveSubconnector class is used for collective communication
+   * based on MPI::ALLGATHER function.
+   */
+  class CollectiveSubconnector : public virtual Subconnector
+  {
+    int nProcesses, *ppBytes, *displ;
+  protected:
+    MPI::Intracomm intracomm_;
+
+  protected:
+    virtual ~CollectiveSubconnector ();
+    CollectiveSubconnector (MPI::Intracomm intracomm);
+    void maybeCommunicate ();
+    int calcCommDataSize (int local_data_size);
+    std::vector<char> getCommData(char *cur_buff, int size);
+    const int* getDisplArr(){return displ;}
+    const int* getSizeArr(){return ppBytes;}
+    virtual void communicate () { };
+    void allocAllgathervArrays ();
+    void freeAllgathervArrays ();
+  };
+
+
+  class DirectRouter;
+  
+
+  class EventOutputCollectiveSubconnector
+    : public OutputSubconnector,
+      public EventSubconnector,
+      public CollectiveSubconnector
+  {
+    DirectRouter* router_;
+  public:
+    EventOutputCollectiveSubconnector ()
+      : CollectiveSubconnector (intracomm_)
+    { }
+    void setRouter (DirectRouter* router) { router_ = router; }
+
+    // the following is part of the MultiConnector protocol
+    void nextBlock () { }
+    unsigned int dataSize ();
+    void setOutputBuffer (void* buffer, unsigned int size);
+    void fillOutputBuffer ();
+
+    void flush (bool& dataStillFlowing) { }
+    void maybeCommunicate () { }
+  };
+
+
+  class EventInputCollectiveSubconnector
+    : public EventInputSubconnector, public CollectiveSubconnector
+  {
+  protected:
+    EventRouter *router_;
+  public:
+    EventInputCollectiveSubconnector (EventRouter *router)
+    : CollectiveSubconnector (intracomm_),
+      router_(router)
+    { }
+    // the following is part of the MultiConnector protocol
+    void processData (void* data, unsigned int size);
+  private:
+    void maybeCommunicate () { }
+  };
+
+
+    class ContCollectiveSubconnector
+      : public ContInputSubconnector,
+	public ContOutputSubconnector,
+	public CollectiveSubconnector {
+      std::multimap< int, Interval> intervals_; //the data we want
+      std::map<int,int> blockSizePerRank_; //contains mapping of rank->size of the communication data
+    										//(size of communication data/nBuffered per rank is constant).
+      int width_; //port width in bytes
+    public:
+      ContCollectiveSubconnector (std::multimap<int, Interval> intervals,
+				  int width,
+				  MPI::Intracomm intracomm,
+				  MPI::Datatype type)
+	: Subconnector(type),
+	  CollectiveSubconnector (intracomm),
+	  intervals_(intervals),
+	  width_(width*type.Get_size ())
+      {
+	allocAllgathervArrays ();
+      }
+      ~ContCollectiveSubconnector ()
+      {
+	void freeAllgathervArrays ();
+      }
+      void initialCommunication (double initialBufferedTicks);
+      void maybeCommunicate ();
+      void flush (bool& dataStillFlowing);
+    private:
+      void communicate();
+      void fillBlockSizes();
+    };
+
+}
+#endif
+#define MUSIC_SUBCONNECTOR_HH
+#endif
diff --git a/src/music/temporal.hh b/src/music/temporal.hh
new file mode 100644
index 0000000..c9beb9e
--- /dev/null
+++ b/src/music/temporal.hh
@@ -0,0 +1,168 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_TEMPORAL_HH
+#include "music/music-config.hh"
+#if MUSIC_USE_MPI
+#define MAX_BUFFERED_NO_VALUE -1
+#define DEFAULT_PACKET_SIZE 64000
+#define EVENT_FREQUENCY_ESTIMATE 10.0
+#define DEFAULT_MESSAGE_MAX_BUFFERED 10
+#include <music/debug.hh>
+#include <music/clock.hh>
+#include <music/connection.hh>
+#include <music/application_graph.hh>
+#include "music/error.hh"
+namespace MUSIC
+{
+
+  class Setup;
+
+  class ConnectionDescriptor
+  {
+  public:
+    int remoteNode;
+    int receiverPort;
+    int maxBuffered;
+    int defaultMaxBuffered; // not used for input connections
+    bool interpolate;
+    bool multiComm;
+    ClockState accLatency;
+    ClockState remoteTickInterval;
+  };
+
+
+  class TemporalNegotiationData
+  {
+  public:
+    int color;
+    int leader;
+    int nProcs;
+    double timebase;
+    ClockState tickInterval;
+    int nOutConnections;
+    int nInConnections;
+    ConnectionDescriptor connection[1];
+  };
+
+
+  class TemporalNegotiatorGraph : public AGraph<TemporalNegotiationData,
+      ConnectionDescriptor>
+  {
+    double timebase_;
+    int nConnections_;
+  public:
+    TemporalNegotiatorGraph (double timebase, int nApps, int color) :
+        AGraph<TemporalNegotiationData, ConnectionDescriptor> (color, nApps), timebase_ (
+            timebase)
+    {
+    }
+
+    void
+    setNConnections (int nConns);
+    int
+    getNConnections ();
+  protected:
+    AEdge<TemporalNegotiationData, ConnectionDescriptor>
+    edge (ANode<TemporalNegotiationData, ConnectionDescriptor> &x, int c)
+    {
+      ConnectionDescriptor& descr = x.data ().connection[c];
+
+      return AEdge<TemporalNegotiationData, ConnectionDescriptor> (x,
+          nodes_[descr.remoteNode], descr);
+    }
+
+    void
+    handleLoop (ANode<TemporalNegotiationData, ConnectionDescriptor> &x,
+        std::vector<AEdge<TemporalNegotiationData, ConnectionDescriptor> > & path);
+  };
+
+  // The TemporalNegotiator negotiates communication timing parameters
+  // with all other applications.
+  class TemporalNegotiator
+  {
+    Setup* setup_;
+    MPI::Group groupWorld;
+    MPI::Group applicationLeaders;
+    MPI::Intracomm negotiationComm;
+
+    int nApplications_; // initialized by createNegotiationCommunicator
+    int nLocalConnections;
+    int nAllConnections;
+
+    std::vector<OutputConnection> outputConnections;
+    std::vector<InputConnection> inputConnections;
+
+    TemporalNegotiatorGraph *nodes;
+
+    TemporalNegotiationData* negotiationBuffer;
+    TemporalNegotiationData* negotiationData;
+
+  public:
+    TemporalNegotiator (Setup* setup);
+    ~TemporalNegotiator ();
+    void
+    negotiate (Clock& localTime, std::vector<Connection*>* connections);
+    TemporalNegotiatorGraph*
+    applicationGraph ();
+
+  private:
+    void
+    separateConnections (std::vector<Connection*>* connections);
+    void
+    createNegotiationCommunicator ();
+    void
+    collectNegotiationData (ClockState ti);
+    void
+    communicateNegotiationData ();
+    void
+    combineParameters ();
+    void
+    loopAlgorithm ();
+    void
+    distributeParameters ();
+    void
+    broadcastNegotiationData ();
+    void
+    receiveNegotiationData ();
+    void
+    fillTemporalNegotiatorGraph ();
+    int
+    negotiationDataSize (int nConnections);
+    int
+    negotiationDataSize (int nBlock, int nConnections);
+    int
+    computeDefaultMaxBuffered (int maxLocalWidth, int eventSize,
+        ClockState tickInterval, double timebase);
+    TemporalNegotiationData*
+    allocNegotiationData (int nBlocks, int nConnections);
+    void
+    freeNegotiationData (TemporalNegotiationData*);
+    int
+    findNodeColor (int leader);
+    ConnectionDescriptor*
+    findInputConnection (int node, int port);
+    bool
+    isLeader ();
+    bool
+    hasPeers ();
+  };
+}
+#endif
+#define MUSIC_TEMPORAL_HH
+#endif
diff --git a/src/music/version.hh.in b/src/music/version.hh.in
new file mode 100644
index 0000000..7dcb9e2
--- /dev/null
+++ b/src/music/version.hh.in
@@ -0,0 +1,34 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MUSIC_VERSION_HH
+
+#include <vector>
+
+#include <music/FIBO.hh>
+
+#define MUSIC_VERSION "@VERSION@"
+
+namespace MUSIC {
+
+  const char* version ();
+  
+}
+
+#define MUSIC_VERSION_HH
+#endif
diff --git a/src/parse.cc b/src/parse.cc
new file mode 100644
index 0000000..12b9d8b
--- /dev/null
+++ b/src/parse.cc
@@ -0,0 +1,129 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/parse.hh"
+
+#include <sstream>
+#include <vector>
+#include <cstdio>
+
+namespace MUSIC {
+  
+  Parser::Parser (std::string s)
+    : in (new std::istringstream (s))
+  {
+  
+  }
+  Parser::~Parser ()
+  {
+	  delete in;
+  }
+  
+  void
+  Parser::ignoreWhitespace ()
+  {
+    while (isspace (in->peek ()))
+      in->ignore ();
+  }
+
+  
+  void
+  Parser::parseString (std::ostringstream& arg, char delim)
+  {
+    while (true)
+      {
+	int c;
+	switch (c = in->get ())
+	  {
+	  case '\'':
+	  case '"':
+	    if (c == delim)
+	      break;
+	  default:
+	    arg << (char) c;
+	    continue;
+	  case '\\':
+	    arg << (char) in->get ();
+	    continue;
+	  case EOF:
+	    // NOTE: generate error message
+	    break;
+	  }
+	break;
+      }  
+  }
+
+  
+  std::string
+  Parser::nextArg ()
+  {
+    std::ostringstream arg;
+    while (true)
+      {
+	int c;
+	switch (c = in->get ())
+	  {
+	  default:
+	    arg << (char) c;
+	    continue;
+	  case '\\':
+	    arg << (char) in->get ();
+	    continue;
+	  case '\'':
+	  case '"':
+	    parseString (arg, c);
+	    continue;
+	  case ' ':
+	  case '\t':
+	  case EOF:
+	    break;
+	  }
+	break;
+      }
+    return arg.str ();
+  }
+
+  
+  char **
+  parseArgs (std::string cmd,
+	     std::string argstring,
+	     int* argc)
+  {
+    Parser in (argstring);
+    std::vector<std::string> args;
+    args.push_back (cmd);
+    in.ignoreWhitespace ();
+
+    while (! in.eof ())
+      args.push_back (in.nextArg ());
+
+    int nArgs = args.size ();
+    char** result = new char*[nArgs + 1];
+    for (int i = 0; i < nArgs; ++i)
+      {
+	int len = args[i].length ();
+	result[i] = new char[len + 1];
+	args[i].copy (result[i], len);
+	result[i][len] = '\0';
+      }
+    result[nArgs] = 0;
+    *argc = nArgs;
+    return result;
+  }
+
+}
diff --git a/src/permutation_index.cc b/src/permutation_index.cc
new file mode 100644
index 0000000..2de7ec5
--- /dev/null
+++ b/src/permutation_index.cc
@@ -0,0 +1,59 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "music/permutation_index.hh"
+#include <algorithm>
+namespace MUSIC {
+  
+  PermutationIndex::PermutationIndex (GlobalIndex* indices, int size)
+  {
+    // NOTE: collapse adjacent intervals where possible?
+    for (int i = 0; i < size; ++i)
+      indices_.push_back (IndexInterval (indices[i],
+					 indices[i] + 1,
+					 indices[i] - i));
+    sort (indices_.begin (), indices_.end ());
+  }
+  
+
+  PermutationIndex::PermutationIndex (std::vector<IndexInterval>& indices)
+    : indices_ (indices)
+  {
+  }
+
+  
+  IndexMap::iterator
+  PermutationIndex::begin ()
+  {
+    return IndexMap::iterator (new iterator (&indices_.front ()));
+  }
+
+  
+  const IndexMap::iterator
+  PermutationIndex::end () const
+  {
+    return IndexMap::iterator (new iterator (&indices_.back () + 1));
+  }
+
+
+  IndexMap*
+  PermutationIndex::copy ()
+  {
+    return new PermutationIndex (indices_);
+  }
+
+}
diff --git a/src/port.cc b/src/port.cc
new file mode 100644
index 0000000..3a49da9
--- /dev/null
+++ b/src/port.cc
@@ -0,0 +1,821 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "music/port.hh"
+
+#if MUSIC_USE_MPI
+#include "music/event_router.hh"
+
+#include "music/setup.hh" // Must be included first on BG/L
+#include "music/error.hh"
+
+namespace MUSIC {
+
+  Port::Port (Setup* s, std::string identifier)
+    : portName_ (identifier), setup_ (s), isMapped_ (false)
+  {
+    s->maybePostponedSetup ();
+    ConnectivityInfo_ = s->portConnectivity (portName_);
+    setup_->addPort (this);
+  }
+
+
+  bool
+  Port::isConnected ()
+  {
+    return ConnectivityInfo_ != Connectivity::NO_CONNECTIVITY;
+  }
+
+
+  void
+  Port::checkConnected (std::string action)
+  {
+    if (!isConnected ())
+      {
+	std::ostringstream msg;
+	msg << "attempt to " << action << " port `" << portName_
+	    << "' which is unconnected";
+	error (msg);
+      }
+  }
+  
+  
+  void
+  Port::assertOutput ()
+  {
+    checkCalledOnce (isMapped_,
+		     "OutputPort::map (...)",
+		     " for port " + portName_);
+    checkConnected ("map");
+    if (ConnectivityInfo_->direction () != ConnectivityInfo::OUTPUT)
+      {
+	std::ostringstream msg;
+	msg << "output port `" << ConnectivityInfo_->portName ()
+	    << "' connected as input";
+	error (msg);
+      }
+  }
+
+
+  void
+  Port::assertInput ()
+  {
+    checkCalledOnce (isMapped_,
+		     "InputPort::map (...)",
+		     " for port " + portName_);
+    checkConnected ("map");
+    if (ConnectivityInfo_->direction () != ConnectivityInfo::INPUT)
+      {
+	std::ostringstream msg;
+	msg << "input port `" << ConnectivityInfo_->portName ()
+	    << "' connected as output";
+	error (msg);
+      }
+  }
+
+
+  bool
+  Port::hasWidth ()
+  {
+    checkConnected ("ask for width of");
+    return ConnectivityInfo_->width () != ConnectivityInfo::NO_WIDTH;
+  }
+
+
+  int
+  Port::width ()
+  {
+    checkConnected ("ask for width of");
+    int w = ConnectivityInfo_->width ();
+    if (w == ConnectivityInfo::NO_WIDTH)
+      {
+	std::ostringstream msg;
+	msg << "width requested for port `" << ConnectivityInfo_->portName ()
+	    << "' which has unspecified width";
+	error (msg);
+      }
+    return w;
+  }
+
+
+  void
+  Port::checkIndexMap (IndexMap* indexMap)
+  {
+    if (indexMap->begin () != indexMap->end ())
+      {
+	IndexMap::iterator i = indexMap->begin ();
+	IndexInterval last = *i;
+	++i;
+	for (; i != indexMap->end (); ++i)
+	  {
+	    if (i->begin () < last.end ())
+	      {
+		std::ostringstream os;
+		os << "Mapping port " << portName_
+		   << " using index map with overlaps: ["
+		   << last.begin () << ", " << last.end () << "), ["
+		   << i->begin () << ", " << i->end () << ")";
+		error (os);
+	      }
+	    last = *i;
+	  }
+      }
+  }
+
+
+  void
+  OutputPort::mapImpl (IndexMap* indices,
+		       Index::Type type,
+		       int maxBuffered,
+		       int dataSize)
+  {
+    checkIndexMap (indices);
+    // The timing algorithm in uses a different definition of
+    // maxBuffered.  While the interface in port.hh counts the number
+    // of "ticks of data" which must be stored, the timing algorithm
+    // counts the offset in time between the processes in sender
+    // ticks.
+    if (maxBuffered != MAX_BUFFERED_NO_VALUE)
+      maxBuffered -= 1;
+	
+    // Retrieve info about all remote connectors of this port
+    PortConnectorInfo portConnections
+      = ConnectivityInfo_->connections ();
+    indices_ = indices;
+    index_type_ = type;
+    for (PortConnectorInfo::iterator info = portConnections.begin ();
+	 info != portConnections.end ();
+	 ++info)
+      {
+	// Create connector
+	Connector* connector = makeConnector (*info);
+	setup_->addConnection (new OutputConnection (connector,
+						     maxBuffered,
+						     dataSize));
+      }
+  }
+
+
+
+  
+  void
+  InputPort::mapImpl (IndexMap* indices,
+		      Index::Type type,
+		      double accLatency,
+		      int maxBuffered,
+		      bool interpolate)
+  {
+    checkIndexMap (indices);
+    // The timing algorithm in uses a different definition of
+    // maxBuffered.  While the interface in port.hh counts the number
+    // of "ticks of data" which must be stored, the timing algorithm
+    // counts the offset in time between the processes in sender
+    // ticks.
+    if (maxBuffered != MAX_BUFFERED_NO_VALUE)
+      maxBuffered -= 1;
+	
+    // Retrieve info about all remote connectors of this port
+    PortConnectorInfo portConnections
+      = ConnectivityInfo_->connections ();
+    PortConnectorInfo::iterator info = portConnections.begin ();
+    indices_ = indices;
+    index_type_ = type;
+    Connector* connector = makeConnector (*info);
+    ClockState integerLatency (accLatency, setup_->timebase ());
+    setup_->addConnection (new InputConnection (connector,
+						maxBuffered,
+						integerLatency,
+						interpolate));
+  }
+
+  
+  /********************************************************************
+   *
+   * Cont Ports
+   *
+   ********************************************************************/
+  
+  void
+  ContOutputPort::map (DataMap* dmap)
+  {
+    assertOutput ();
+    int maxBuffered = MAX_BUFFERED_NO_VALUE;
+    mapImpl (dmap, maxBuffered);
+  }
+
+  
+  void
+  ContOutputPort::map (DataMap* dmap, int maxBuffered)
+  {
+    assertOutput ();
+    if (maxBuffered <= 0)
+      {
+	error ("ContOutputPort::map: maxBuffered should be a positive integer");
+      }
+    mapImpl (dmap, maxBuffered);
+  }
+
+  
+  void
+  ContOutputPort::mapImpl (DataMap* dmap,
+			   int maxBuffered)
+  {
+    sampler.configure (dmap);
+    type_ = dmap->type ();
+    OutputPort::mapImpl (dmap->indexMap (),
+				       Index::GLOBAL,
+				       maxBuffered,
+				       0);
+  }
+
+
+  Connector*
+  ContOutputPort::makeConnector (ConnectorInfo connInfo)
+  {
+	  Connector * conn;
+	  if(connInfo.communicationType() ==  ConnectorInfo::POINTTOPOINT){
+		  conn =  new ContOutputConnector (connInfo,
+				  indices_,
+		  		  index_type_,
+				  setup_->communicator (),
+				  sampler,
+				  type_);
+	  }
+	  else
+		  conn = new ContOutputCollectiveConnector(connInfo,
+				  indices_,
+		  		  index_type_,
+				  setup_->communicator (),
+				  sampler,
+				  type_);
+
+	  return conn;
+  }
+  
+  
+  void
+  ContOutputPort::tick ()
+  {
+    sampler.newSample ();
+  }
+
+
+  void
+  ContInputPort::map (DataMap* dmap, double delay, bool interpolate)
+  {
+    assertInput ();
+    int maxBuffered = MAX_BUFFERED_NO_VALUE;
+    mapImpl (dmap,
+	     delay,
+	     maxBuffered,
+	     interpolate);
+  }
+
+  
+  void
+  ContInputPort::map (DataMap* dmap,
+		      int maxBuffered,
+		      bool interpolate)
+  {
+    assertInput ();
+    mapImpl (dmap,
+	     0.0,
+	     maxBuffered,
+	     interpolate);
+  }
+
+  
+  void
+  ContInputPort::map (DataMap* dmap,
+		      double delay,
+		      int maxBuffered,
+		      bool interpolate)
+  {
+    assertInput ();
+    mapImpl (dmap,
+	     delay,
+	     maxBuffered,
+	     interpolate);
+  }
+
+  
+  void
+  ContInputPort::mapImpl (DataMap* dmap,
+			  double delay,
+			  int maxBuffered,
+			  bool interpolate)
+  {
+    sampler.configure (dmap);
+    delay_ = delay;
+    type_ = dmap->type ();
+    InputPort::mapImpl (dmap->indexMap (),
+				      Index::GLOBAL,
+				      delay,
+				      maxBuffered,
+				      interpolate);
+  }
+
+  
+  Connector*
+  ContInputPort::makeConnector (ConnectorInfo connInfo)
+  {
+	  Connector * conn;
+	  if(connInfo.communicationType() ==  ConnectorInfo::POINTTOPOINT){
+		  conn = new ContInputConnector (connInfo,
+				  indices_,
+		  		  index_type_,
+				  setup_->communicator (),
+				  sampler,
+				  type_,
+				  delay_);
+	  }
+	  else
+		  conn = new ContInputCollectiveConnector (connInfo,
+				  indices_,
+		  		  index_type_,
+				  setup_->communicator (),
+				  sampler,
+				  type_,
+				  delay_);
+	  return conn;
+  }
+
+  
+  /********************************************************************
+   *
+   * Event Ports
+   *
+   ********************************************************************/
+
+  EventOutputPort::EventOutputPort (Setup* s, std::string id)
+    : Port (s, id), routingMap (new OutputRoutingMap () /* deleted in buildTable */)
+  {
+    /* remedius
+     * Depending on the communication type (<commType>) and
+     * processing method (<procMethod>) that was introduced as
+     * runtime configuration options,
+     * particular processing router should be created on the output side.
+     * When collective communication type is used,
+     * then the processing method has to be TABLE on the output side, as in this case
+     * the processing on the output side means just an insertion of the event to the buffer.
+     * The difference between point-to-point and collective communication types is that on the output side
+     * in the latest case we have only one common buffer (one CollectiveSubconnector) and processing is happening on the receiver side.
+     */
+    if (isConnected ())
+      {
+	bool mixed = false;
+	PortConnectorInfo::iterator c = ConnectivityInfo_->connections ().begin ();
+	int commType = c->communicationType ();
+	int procMethod = c->processingMethod ();
+	for (++c; c != ConnectivityInfo_->connections ().end (); ++c)
+	  {
+	    if (c->processingMethod () != procMethod)
+	      error ("MUSIC: can't use both tree and table for same port");
+	    if (c->communicationType () != commType)
+	      mixed = true;
+	  }
+	if (!mixed)
+	  {
+	    if (commType == ConnectorInfo::COLLECTIVE)
+	      router = new DirectRouter ();
+	    else if (procMethod == ConnectorInfo::TREE)
+	      router = new TreeProcessingOutputRouter ();
+	    else
+	      router = new TableProcessingOutputRouter ();
+	  }
+	else
+	  {
+	    if (procMethod == ConnectorInfo::TREE)
+	      router = new HybridTreeProcessingOutputRouter ();
+	    else
+	      router = new HybridTableProcessingOutputRouter ();
+	  }
+      }
+  }
+
+
+  EventOutputPort::~EventOutputPort()
+ {
+   if (router != NULL)
+     delete router;
+ }
+  
+  void 
+  EventOutputPort::mapImpl (IndexMap* indices,
+			    Index::Type type,
+			    int maxBuffered)
+  {
+    OutputPort::mapImpl (indices, type, maxBuffered, (int) sizeof (Event));
+  }
+
+  void
+  EventOutputPort::map (IndexMap* indices, Index::Type type)
+  {
+    assertOutput ();
+    EventOutputPort::mapImpl (indices, type, MAX_BUFFERED_NO_VALUE);
+  }
+
+  
+  void
+  EventOutputPort::map (IndexMap* indices,
+			Index::Type type,
+			int maxBuffered)
+  {
+    assertOutput ();
+    if (maxBuffered <= 0)
+      {
+	error ("EventOutputPort::map: maxBuffered should be a positive integer");
+      }
+    EventOutputPort::mapImpl (indices, type, maxBuffered);
+  }
+
+  
+  Connector*
+  EventOutputPort::makeConnector (ConnectorInfo connInfo)
+  {
+    Connector *conn;
+    // we need to choose a right connector according to the communication type
+    if (connInfo.communicationType () ==  ConnectorInfo::POINTTOPOINT)
+      conn = new EventOutputConnector (connInfo,
+				       indices_,
+				       index_type_,
+				       setup_->communicator (),
+				       routingMap);
+    else
+      conn = new EventOutputCollectiveConnector
+	(connInfo,
+	 indices_,
+	 index_type_,
+	 setup_->communicator (),
+	 router->directRouter ());
+
+    return conn;
+  }
+  
+  
+  void
+  EventOutputPort::insertEventImpl (double t, int id)
+  {
+    router->processEvent(t, id);
+  }
+
+  void
+  EventOutputPort::insertEvent (double t, GlobalIndex id)
+  {
+    insertEventImpl(t, id);
+  }
+
+  
+  void
+  EventOutputPort::insertEvent (double t, LocalIndex id)
+  {
+    insertEventImpl(t, id);
+  }
+
+  void
+  EventOutputPort::buildTable ()
+  {
+    routingMap->fillRouter (router);
+    delete routingMap;
+    router->buildTable ();
+  }
+
+
+  EventInputPort::EventInputPort (Setup* s, std::string id)
+    : Port (s, id)
+  {
+
+  }
+  
+
+  void
+  EventInputPort::map (IndexMap* indices,
+		       EventHandlerGlobalIndex* handleEvent,
+		       double accLatency)
+  {
+    assertInput ();
+    int maxBuffered = MAX_BUFFERED_NO_VALUE;
+    mapImpl (indices,
+	     Index::GLOBAL,
+	     EventHandlerPtr (handleEvent),
+	     accLatency,
+	     maxBuffered);
+  }
+
+  
+  void
+  EventInputPort::map (IndexMap* indices,
+		       EventHandlerLocalIndex* handleEvent,
+		       double accLatency)
+  {
+    assertInput ();
+    int maxBuffered = MAX_BUFFERED_NO_VALUE;
+    mapImpl (indices,
+	     Index::LOCAL,
+	     EventHandlerPtr (handleEvent),
+	     accLatency,
+	     maxBuffered);
+  }
+
+  
+  void
+  EventInputPort::map (IndexMap* indices,
+		       EventHandlerGlobalIndex* handleEvent,
+		       double accLatency,
+		       int maxBuffered)
+  {
+    assertInput ();
+    if (maxBuffered <= 0)
+      {
+	error ("EventInputPort::map: maxBuffered should be a positive integer");
+      }
+    mapImpl (indices,
+	     Index::GLOBAL,
+	     EventHandlerPtr (handleEvent),
+	     accLatency,
+	     maxBuffered);
+  }
+
+  
+  void
+  EventInputPort::map (IndexMap* indices,
+		       EventHandlerLocalIndex* handleEvent,
+		       double accLatency,
+		       int maxBuffered)
+  {
+    assertInput ();
+    if (maxBuffered <= 0)
+      {
+	error ("EventInputPort::map: maxBuffered should be a positive integer");
+      }
+    mapImpl (indices,
+	     Index::LOCAL,
+	     EventHandlerPtr (handleEvent),
+	     accLatency,
+	     maxBuffered);
+  }
+
+  
+  void
+  EventInputPort::mapImpl (IndexMap* indices,
+			   Index::Type type,
+			   EventHandlerPtr handleEvent,
+			   double accLatency,
+			   int maxBuffered)
+  {
+    type_ = type;
+    handleEvent_ = handleEvent;
+    InputPort::mapImpl (indices,
+				      type,
+				      accLatency,
+				      maxBuffered,
+				      false);
+  }
+
+  
+  Connector*
+  EventInputPort::makeConnector (ConnectorInfo connInfo)
+  {
+	  // we need to choose a right connector according to the communication type
+	  Connector *conn;
+	  if(connInfo.communicationType() ==  ConnectorInfo::POINTTOPOINT)
+		  conn =   new EventInputConnector (connInfo,
+		  			  indices_,
+		  			  index_type_,
+		  			  setup_->communicator (),
+		  			  handleEvent_);
+	  else
+		  conn = new EventInputCollectiveConnector(connInfo,
+	  	 			indices_,
+		  			index_type_,
+	  	 			setup_->communicator (),
+	  	 			handleEvent_);
+
+	 return conn;
+  }
+
+  
+  EventHandlerGlobalIndexProxy*
+  EventInputPort::allocEventHandlerGlobalIndexProxy (void (*eh) (double, int))
+  {
+    cEventHandlerGlobalIndex = EventHandlerGlobalIndexProxy (eh);
+    return &cEventHandlerGlobalIndex;
+  }
+
+  
+  EventHandlerLocalIndexProxy*
+  EventInputPort::allocEventHandlerLocalIndexProxy (void (*eh) (double, int))
+  {
+    cEventHandlerLocalIndex = EventHandlerLocalIndexProxy (eh);
+    return &cEventHandlerLocalIndex;
+  }
+
+  /********************************************************************
+   *
+   * Message Ports
+   *
+   ********************************************************************/
+
+  MessagePort::MessagePort (Setup* s)
+    : rank_ (s->communicator ().Get_rank ())
+  {
+  }
+  
+  
+  MessageOutputPort::MessageOutputPort (Setup* s, std::string id)
+    : Port (s, id), MessagePort (s)
+  {
+  }
+
+  
+  void
+  MessageOutputPort::map ()
+  {
+    assertOutput ();
+    int maxBuffered = MAX_BUFFERED_NO_VALUE;
+    mapImpl (maxBuffered);
+  }
+
+  
+  void
+  MessageOutputPort::map (int maxBuffered)
+  {
+    assertOutput ();
+    if (maxBuffered <= 0)
+      {
+	error ("MessageOutputPort::map: maxBuffered should be a positive integer");
+      }
+    mapImpl (maxBuffered);
+  }
+
+  
+  void
+  MessageOutputPort::mapImpl (int maxBuffered)
+  {
+    // Identify ourselves
+    LinearIndex indices (rank_, 1);
+    OutputPort::mapImpl (&indices,
+				       Index::GLOBAL,
+				       maxBuffered,
+				       1);
+  }
+  
+  
+  Connector*
+  MessageOutputPort::makeConnector (ConnectorInfo connInfo)
+  {
+    return new MessageOutputConnector (connInfo,
+				       indices_,
+		  			   index_type_,
+				       setup_->communicator (),
+				       buffers);
+  }
+  
+  
+  void
+  MessageOutputPort::insertMessage (double t, void* msg, size_t size)
+  {
+    // One output buffer per OutputConnector (since different
+    // connectors may need to send at different times)
+    for (std::vector<FIBO*>::iterator b = buffers.begin ();
+	 b != buffers.end ();
+	 ++b)
+      {
+	MessageHeader header (t, size);
+	(*b)->insert (header.data (), sizeof (MessageHeader));
+	(*b)->insert (msg, size);
+      }
+  }
+
+  
+  MessageInputPort::MessageInputPort (Setup* s, std::string id)
+    : Port (s, id), MessagePort (s)
+  {
+  }
+
+  
+  void
+  MessageInputPort::map (MessageHandler* handleMessage,
+			 double accLatency)
+  {
+    assertInput ();
+    int maxBuffered = MAX_BUFFERED_NO_VALUE;
+    mapImpl (handleMessage,
+	     accLatency,
+	     maxBuffered);
+  }
+
+  
+  void
+  MessageInputPort::map (int maxBuffered)
+  {
+    assertInput ();
+    if (maxBuffered <= 0)
+      {
+	error ("MessageInputPort::map: maxBuffered should be a positive integer");
+      }
+    mapImpl (0,
+	     0.0,
+	     maxBuffered);
+  }
+
+  
+  void
+  MessageInputPort::map (double accLatency,
+			 int maxBuffered)
+  {
+    assertInput ();
+    if (maxBuffered <= 0)
+      {
+	error ("MessageInputPort::map: maxBuffered should be a positive integer");
+      }
+    mapImpl (0,
+	     accLatency,
+	     maxBuffered);
+  }
+
+  
+  void
+  MessageInputPort::map (MessageHandler* handleMessage,
+			 int maxBuffered)
+  {
+    assertInput ();
+    if (maxBuffered <= 0)
+      {
+	error ("MessageInputPort::map: maxBuffered should be a positive integer");
+      }
+    mapImpl (handleMessage,
+	     0.0,
+	     maxBuffered);
+  }
+
+  
+  void
+  MessageInputPort::map (MessageHandler* handleMessage,
+			 double accLatency,
+			 int maxBuffered)
+  {
+    assertInput ();
+    if (maxBuffered <= 0)
+      {
+	error ("MessageInputPort::map: maxBuffered should be a positive integer");
+      }
+    mapImpl (handleMessage,
+	     accLatency,
+	     maxBuffered);
+  }
+
+  
+  void
+  MessageInputPort::mapImpl (MessageHandler* handleMessage,
+			     double accLatency,
+			     int maxBuffered)
+  {
+    handleMessage_ = handleMessage;
+    // Receive from everybody
+    LinearIndex indices (0, handleMessage ? Index::WILDCARD_MAX : 0);
+    InputPort::mapImpl (&indices,
+				      Index::GLOBAL,
+				      accLatency,
+				      maxBuffered,
+				      false);
+  }
+
+  
+  Connector*
+  MessageInputPort::makeConnector (ConnectorInfo connInfo)
+  {
+    return new MessageInputConnector (connInfo,
+				      indices_,
+		  			  index_type_,
+				      handleMessage_,
+				      setup_->communicator ());
+  }
+
+  
+  MessageHandlerProxy*
+  MessageInputPort::allocMessageHandlerProxy (void (*mh) (double,
+								     void*,
+								     size_t))
+  {
+    cMessageHandler = MessageHandlerProxy (mh);
+    return &cMessageHandler;
+  }
+
+  
+}
+#endif
diff --git a/src/predict_rank-c.cc b/src/predict_rank-c.cc
new file mode 100644
index 0000000..744425e
--- /dev/null
+++ b/src/predict_rank-c.cc
@@ -0,0 +1,27 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2011 CSC, KTH
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/predict_rank.hh"
+
+extern "C" {
+#include "music/predict_rank-c.h"
+
+  int MUSIC_predictRank (int argc, char **argv) {
+    return MUSIC::predictRank (argc, argv);
+  }
+}
diff --git a/src/predict_rank.cc b/src/predict_rank.cc
new file mode 100644
index 0000000..8050d98
--- /dev/null
+++ b/src/predict_rank.cc
@@ -0,0 +1,29 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2011 CSC, KTH
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/predict_rank.hh"
+
+#include "mpidep/mpidep.hh"
+
+namespace MUSIC {
+
+  int predictRank (int argc, char** argv) {
+    return getRank (argc, argv);
+  }
+
+}
diff --git a/src/runtime.cc b/src/runtime.cc
new file mode 100644
index 0000000..fe6ed53
--- /dev/null
+++ b/src/runtime.cc
@@ -0,0 +1,535 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007-2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//#define MUSIC_DEBUG
+//#define MUSIC_AFTER_RUNTIME_CONSTRUCTOR_REPORT
+#include "music/runtime.hh"
+
+#if MUSIC_USE_MPI
+
+#include <mpi.h>
+
+#include "music/temporal.hh"
+#include "music/error.hh"
+#include "music/connection.hh"
+#include "music/memory.hh"
+
+#include <algorithm>
+#include <iostream>
+#include <set>
+#include <cassert>
+
+namespace MUSIC
+{
+
+  bool Runtime::isInstantiated_ = false;
+
+
+  Runtime::Runtime (Setup* s, double h)
+    : mAgent (0)
+  {
+    checkInstantiatedOnce (isInstantiated_, "Runtime");
+    s->maybePostponedSetup ();
+
+    app_name = s->applicationName ();
+    leader_ = s->leader ();
+
+    /* remedius
+     * new type of subconnectors for collective communication was created.
+     */
+    //CollectiveSubconnectors collectiveSubconnectors;
+    // Setup the MUSIC clock
+    localTime = Clock (s->timebase (), h);
+
+    comm = s->communicator ();
+
+    /* remedius
+     * copy ports in order to delete them afterwards (it was probably a memory leak in previous revision)
+     */
+    for (std::vector<Port *>::iterator it = s->ports ()->begin ();
+        it < s->ports ()->end (); it++)
+      ports.push_back ( (*it));
+
+    Connections* connections = s->connections ();
+
+    scheduler = new Scheduler (comm, leader_);
+    if (s->launchedByMusic ())
+      {
+        takeTickingPorts (s);
+
+        // create a total order for connectors and
+        // establish connection to peers
+        connectToPeers (connections);
+
+        // specialize connectors and fill up connectors vector
+        specializeConnectors (connections);
+        // from here we can start using the vector `connectors'
+        // negotiate where to route data and fill up subconnector vectors
+        spatialNegotiation ();
+
+        // build data routing tables
+        buildTables (s);
+        takePreCommunicators ();
+        takePostCommunicators ();
+        // negotiate timing constraints for synchronizers
+        temporalNegotiation (s, connections);
+#if 0
+        if (needsMultiCommunication ())
+          {
+#endif
+        sAgents.push_back (mAgent = new MulticommAgent (scheduler));
+        scheduler->setAgent (mAgent);
+#if 0
+      }
+#endif
+        sAgents.push_back (new UnicommAgent (scheduler));
+        scheduler->setAgent (sAgents[sAgents.size () - 1]);
+
+        // final initialization before simulation starts
+        initialize (s);
+      }
+    else
+      {
+	sAgents.push_back (new DummyAgent (scheduler));
+	scheduler->setAgent (sAgents[0]);
+	scheduler->initializeAgentState ();
+      }
+
+    delete s;
+#ifdef MUSIC_AFTER_RUNTIME_CONSTRUCTOR_REPORT
+    if (MPI::COMM_WORLD.Get_rank () == 0)
+    reportMem ();
+#if 0
+    // Code used for debugging and analysis
+    for (std::vector<Connector*>::iterator connector = connectors.begin ();
+        connector != connectors.end ();
+        ++connector)
+    (*connector)->report ();
+#endif
+#endif
+  }
+
+
+  Runtime::~Runtime ()
+  {
+    // delete connectors
+    for (std::vector<Connector*>::iterator connector = connectors.begin ();
+        connector != connectors.end (); ++connector)
+      delete *connector;
+#if 0
+    /* MDJ 2012-08-07
+     Some applications assume that they need to delete the ports.
+     Until we have made a decision what is the proper usage pattern,
+     this code is disabled. */
+
+    // delete ports
+    for (std::vector<Port *>::iterator it=ports.begin(); it < ports.end(); it++ )
+    delete (*it);
+#endif
+    for (std::vector<SchedulerAgent *>::iterator it = sAgents.begin ();
+        it != sAgents.end (); it++)
+      delete (*it);
+    delete scheduler;
+    isInstantiated_ = false;
+  }
+
+
+  bool
+  Runtime::needsMultiCommunication ()
+  {
+    std::vector<Connector*>::iterator c;
+    for (c = connectors.begin (); c != connectors.end (); ++c)
+      if ((*c)->needsMultiCommunication ())
+	return true;
+    return false;
+  }
+
+  void
+  Runtime::takeTickingPorts (Setup* s)
+  {
+    std::vector<Port*>::iterator p;
+    for (p = ports.begin (); p != ports.end (); ++p)
+      {
+        TickingPort* tp = dynamic_cast<TickingPort*> (*p);
+        if (tp != NULL)
+          tickingPorts.push_back (tp);
+      }
+  }
+
+
+  void
+  Runtime::takePreCommunicators ()
+  {
+    std::vector<Connector*>::iterator c;
+    for (c = connectors.begin (); c != connectors.end (); ++c)
+      {
+        PreCommunicationConnector* preCommunicationConnector =
+            dynamic_cast<PreCommunicationConnector*> (*c);
+        if (preCommunicationConnector != NULL)
+          preCommunication.push_back (preCommunicationConnector);
+      }
+  }
+
+
+  void
+  Runtime::takePostCommunicators ()
+  {
+    std::vector<Connector*>::iterator c;
+    for (c = connectors.begin (); c != connectors.end (); ++c)
+      {
+        PostCommunicationConnector* postCommunicationConnector =
+            dynamic_cast<PostCommunicationConnector*> (*c);
+        if (postCommunicationConnector != NULL)
+          postCommunication.push_back (postCommunicationConnector);
+      }
+  }
+
+  // This predicate gives a total order for connectors which is the
+  // same on the sender and receiver sides.  It belongs here rather
+  // than in connector.hh or connector.cc since it is connected to the
+  // connect algorithm.
+  bool
+  lessConnection (const Connection* cn1, const Connection* cn2)
+  {
+    Connector* c1 = cn1->connector ();
+    Connector* c2 = cn2->connector ();
+    return (c1->receiverAppName () < c2->receiverAppName ()
+        || (c1->receiverAppName () == c2->receiverAppName ()
+            && c1->receiverPortName () < c2->receiverPortName ()));
+  }
+
+
+  void
+  Runtime::connectToPeers (Connections* connections)
+  {
+    // This ordering is necessary so that both sender and receiver
+    // in each pair sets up communication at the same point in time
+    //
+    // Note that we don't need to use the dead-lock scheme used in
+    // build_schedule () here.
+    //
+    sort (connections->begin (), connections->end (), lessConnection);
+
+    for (Connections::iterator c = connections->begin ();
+        c != connections->end (); ++c)
+      (*c)->connector ()->createIntercomm ();
+  }
+
+
+  void
+  Runtime::specializeConnectors (Connections* connections)
+  {
+    for (Connections::iterator c = connections->begin ();
+        c != connections->end (); ++c)
+      {
+        Connector *connector = (*c)->connector ();
+        connector->specialize (localTime);
+        //(*c)->setConnector (connector);
+        connectors.push_back (connector);
+      }
+  }
+
+
+  void
+  Runtime::spatialNegotiation ()
+  {
+    // Let each connector pair setup their inter-communicators
+    // and create all required subconnectors.
+    unsigned int multiId = 0;
+    for (std::vector<Connector*>::iterator c = connectors.begin ();
+        c != connectors.end (); ++c)
+      {
+        // negotiate and fill up vectors passed as arguments
+        (*c)->spatialNegotiation ();
+        multiId |= (*c)->idFlag ();
+      }
+  }
+
+
+  void
+  Runtime::buildTables (Setup* s)
+  {
+    for (std::vector<Port*>::iterator p = ports.begin (); p != ports.end ();
+        ++p)
+      (*p)->buildTable ();
+  }
+
+
+  void
+  Runtime::temporalNegotiation (Setup* s, Connections* connections)
+  {
+    // Temporal negotiation is done globally by a serial algorithm
+    // which yields the same result in each process
+    s->temporalNegotiator ()->negotiate (localTime, connections);
+  }
+
+
+  MPI::Intracomm
+  Runtime::communicator ()
+  {
+    return comm;
+  }
+
+
+  void
+  Runtime::initialize (Setup* s)
+  {
+    scheduler->initialize (s->temporalNegotiator ()->applicationGraph (),
+        connectors);
+#if 0
+    if (mAgent)
+      mAgent->initialize (localTime, comm, leader_, connectors);
+#endif
+    // scheduler->nextCommunication (localTime, schedule);
+    scheduler->tick (localTime);
+    // compensate for first localTime.tick () in Runtime::tick ()
+    localTime.ticks (-1);
+    // the time zero tick () (where we may or may not communicate)
+    tick ();
+  }
+
+
+  void
+  Runtime::finalize ()
+  {
+#if 1
+    scheduler->finalize (localTime, connectors);
+#else
+    /* remedius
+     * set of receiver port codes that still has to be finalized
+     */
+    std::set<int> cnn_ports;
+    for (std::vector<Connector*>::iterator c = connectors.begin ();
+        c != connectors.end ();
+        ++c)
+    cnn_ports.insert ((*c)->receiverPortCode ());
+
+    /*
+     * finalize communication
+     *
+     * For ordinary connectors, Connector::finalize () is called
+     * repeatedly until Connector::isFinalized () returns true.
+     *
+     * For connectors participating in multiConnectors,
+     * Connector::finalize () is called, followed by a multi-tick
+     * until Connector::isFInalized () returns true.
+     */
+
+    std::vector<Connector*> cCache;
+
+    if (!schedule.empty ())
+    do
+      {
+        std::vector<std::pair<double, Connector*> >::iterator comm;
+        for (comm = schedule.begin (); comm != schedule.end (); ++comm)
+          {
+            Connector* connector = comm->second;
+            if (connector == NULL
+                || (cnn_ports.find (connector->receiverPortCode ())
+                    == cnn_ports.end ()))
+            continue; // already finalized
+
+            if (!connector->idFlag ())
+              {
+                if (connector->isFinalized ())
+                // an output port was finalized in tick ()
+                  {
+                    cnn_ports.erase (connector->receiverPortCode ());
+                    continue;
+                  }
+                // finalize () needs to come after isFinalized check
+                // since it can itself set finalized state
+                connector->finalize ();
+                continue;
+              }
+
+            // all multiconnector code should go into scheduler
+            // this is a temporary solution
+            int remoteLeader = connector->remoteLeader ();
+            bool direction = connector->isInput ();
+            unsigned int multiId = connector->idFlag ();
+            cCache.clear ();
+            cCache.push_back (connector);
+            // yes, horrible quadratic algorithm for now
+            for (std::vector< std::pair<double, Connector*> >::iterator c
+                = comm + 1;
+                c != schedule.end ();
+                ++c)
+              {
+                if (c->second != NULL
+                    && c->second->idFlag ()
+                    && c->second->remoteLeader () == remoteLeader
+                    && c->second->isInput () == direction)
+                  {
+                    cCache.push_back (c->second);
+                    multiId |= c->second->idFlag ();
+                    c->second = NULL; // taken
+                  }
+              }
+
+            bool isFinalized = true;
+            for (std::vector<Connector*>::iterator c = cCache.begin ();
+                c != cCache.end ();
+                ++c)
+              {
+                if (!(*c)->isFinalized ())
+                isFinalized = false;
+              }
+
+            if (isFinalized)
+              {
+                for (std::vector<Connector*>::iterator c = cCache.begin ();
+                    c != cCache.end ();
+                    ++c)
+                cnn_ports.erase ((*c)->receiverPortCode ());
+                continue;
+              }
+
+            for (std::vector<Connector*>::iterator c = cCache.begin ();
+                c != cCache.end ();
+                ++c)
+            if (!(*c)->isFinalized ())
+            (*c)->finalize ();
+
+            if (multiConnectors[multiId] == NULL)
+              {
+                std::cout << "Rank " << MPI::COMM_WORLD.Get_rank ()
+                << " aborting on multiId " << multiId
+                << " remote leader = " << connector->remoteLeader ()
+                << std::endl;
+                assert (0);
+              }
+            multiConnectors[multiId]->tick ();
+            //cCache.clear ();
+          }
+
+        schedule.clear ();
+        scheduler->nextCommunication (localTime, schedule);
+        //scheduler->tick(localTime);
+        for (std::vector<PostCommunicationConnector*>::iterator c =
+            postCommunication.begin ();
+            c != postCommunication.end ();
+            ++c)
+        (*c)->postCommunication ();
+      }
+    while (!cnn_ports.empty ());
+#endif
+
+#if defined (OPEN_MPI) && MPI_VERSION <= 2
+    // This is needed in OpenMPI version <= 1.2 for the freeing of the
+    // intercommunicators to go well
+    MPI::COMM_WORLD.Barrier ();
+#endif
+    for (std::vector<Connector*>::iterator connector = connectors.begin ();
+        connector != connectors.end (); ++connector)
+      (*connector)->freeIntercomm ();
+
+    MPI::Finalize ();
+  }
+
+
+  void
+  Runtime::tick ()
+  {
+
+    // Update local time
+    localTime.tick ();
+    // ContPorts do some per-tick initialization here
+    std::vector<TickingPort*>::iterator p;
+    for (p = tickingPorts.begin (); p != tickingPorts.end (); ++p)
+      (*p)->tick ();
+    // ContOutputConnectors sample data
+    for (std::vector<PreCommunicationConnector*>::iterator c =
+        preCommunication.begin (); c != preCommunication.end (); ++c)
+      (*c)->preCommunication ();
+
+#if 1
+    scheduler->tick (localTime);
+#else
+    if (!schedule.empty ())
+    while (schedule[0].first <= localTime.time())
+      {
+        std::vector< std::pair<double, Connector*> >::iterator comm;
+        for (comm = schedule.begin ();
+            comm != schedule.end() && comm->first <= localTime.time ();
+            ++comm)
+          {
+            if (comm->second == NULL || comm->second->isFinalized ())
+            continue;
+
+            Connector* connector = comm->second;
+
+            if (!connector->idFlag ())
+              {
+                // here standard connectors are handled
+                connector->tick ();
+                continue;
+              }
+
+            // all multiconnector code should go into scheduler
+            // this is a temporary solution
+            int remoteLeader = connector->remoteLeader ();
+            bool direction = connector->isInput ();
+            unsigned int multiId = connector->idFlag ();
+            //cCache.push_back (connector);
+            // yes, horrible quadratic algorithm for now
+            for (std::vector< std::pair<double, Connector*> >::iterator c
+                = comm + 1;
+                c != schedule.end () && c->first <= localTime.time();
+                ++c)
+              {
+                if (c->second != NULL
+                    && c->second->idFlag ()
+                    && c->second->remoteLeader () == remoteLeader
+                    && c->second->isInput () == direction)
+                  {
+                    //cCache.push_back (c->second);
+                    multiId |= c->second->idFlag ();
+                    c->second = NULL;// taken
+                  }
+              }
+
+            //if (MPI::COMM_WORLD.Get_rank () == 2)
+            //  std::cout << "multiId = " << multiId << std::endl;
+            if (multiConnectors[multiId] == NULL)
+              {
+                assert (0);
+              }
+            multiConnectors[multiId]->tick ();
+            //cCache.clear ();
+          }
+        schedule.erase (schedule.begin (), comm);
+        scheduler->nextCommunication (localTime, schedule);
+      }*/
+#endif
+
+    // ContInputConnectors write data to application here
+    for (std::vector<PostCommunicationConnector*>::iterator c =
+        postCommunication.begin (); c != postCommunication.end (); ++c)
+      (*c)->postCommunication ();
+  }
+
+
+  double
+  Runtime::time ()
+  {
+    return localTime.time ();
+  }
+
+}
+#endif
diff --git a/src/sampler.cc b/src/sampler.cc
new file mode 100644
index 0000000..f14c986
--- /dev/null
+++ b/src/sampler.cc
@@ -0,0 +1,239 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/sampler.hh"
+
+#include "music/debug.hh"
+
+#if MUSIC_USE_MPI
+
+// array_data.hh needs to be included first since it causes inclusion
+// of mpi.h (in data_map.hh).  mpi.h must be included before other
+// header files on BG/L
+#include "music/array_data.hh"
+#include "music/index_map_factory.hh"
+#include "music/error.hh"
+
+#include <cstring>
+
+
+
+namespace MUSIC {
+
+  Sampler::Sampler ()
+    : dataMap_ (0), interpolationDataMap_ (0)
+  {
+  }
+
+
+  Sampler::~Sampler ()
+  {
+    if (dataMap_ != 0)
+      delete dataMap_;
+    if (interpolationDataMap_ != 0)
+      delete interpolationDataMap_;
+  }
+  
+
+  /*
+   * Called during port mapping
+   */
+  void
+  Sampler::configure (DataMap* dataMap)
+  {
+    dataMap_ = dataMap->copy ();
+  }
+
+
+  void
+  Sampler::initialize ()
+  {
+    elementSize = dataMap_->type ().Get_size ();
+    
+    size = 0;
+    IndexMap* indices = dataMap_->indexMap ();
+    IndexMapFactory newIndices;
+    for (IndexMap::iterator i = indices->begin ();
+	 i != indices->end ();
+	 ++i)
+      {
+	int localIndex = size;
+	newIndices.add (i->begin (), i->end (), localIndex);
+	size += i->end () - i->begin ();
+      }
+    newIndices.build ();
+
+    prevSample_ = new ContDataT[elementSize * size];
+    sample_ = new ContDataT[elementSize * size];
+    interpolationData_ = new ContDataT[elementSize * size];
+
+    interpolationDataMap_ = new ArrayData (interpolationData_,
+					   dataMap_->type (),
+					   &newIndices);
+
+    MUSIC_LOGR ("prev = " << static_cast<void*> (prevSample_)
+		<< ", sample = " << static_cast<void*> (sample_)
+		<< ", interp = " << static_cast<void*> (interpolationData_));
+  }
+
+  
+  /*
+   * Called during configuration of interpolating connectors
+   */
+  DataMap*
+  Sampler::interpolationDataMap ()
+  {
+    if (interpolationDataMap_ == 0)
+      initialize ();
+    
+    return interpolationDataMap_;
+  }
+
+
+  void
+  Sampler::newSample ()
+  {
+    hasSampled = false;
+  }
+
+
+  void
+  Sampler::sampleOnce ()
+  {
+    if (!hasSampled)
+      {
+	sample ();
+	hasSampled = true;
+      }
+  }
+
+
+  void
+  Sampler::sample ()
+  {
+    ContDataT* dest = insert ();
+
+    int pos = 0;
+    IndexMap* indices = dataMap_->indexMap ();
+    for (IndexMap::iterator i = indices->begin ();
+	 i != indices->end ();
+	 ++i)
+      {
+	ContDataT* src = static_cast<ContDataT*> (dataMap_->base ());
+	int iSize = elementSize * (i->end () - i->begin ());
+	memcpy (dest + pos,
+		src + elementSize * (i->begin () - i->local ()),
+		iSize);
+	pos += iSize;
+      }
+  }
+
+  
+  ContDataT*
+  Sampler::insert ()
+  {
+    swapBuffers (sample_, prevSample_);
+    return sample_;
+  }
+
+  
+  void
+  Sampler::swapBuffers (ContDataT*& b1, ContDataT*& b2)
+  {
+    ContDataT* tmp;
+    tmp = b1;
+    b1 = b2;
+    b2 = tmp;
+  }
+
+
+  void
+  Sampler::interpolate (double interpolationCoefficient)
+  {
+    interpolateTo (interpolationDataMap_, interpolationCoefficient);
+  }
+  
+  
+  void
+  Sampler::interpolateToApplication (double interpolationCoefficient)
+  {
+    interpolateTo (dataMap_, interpolationCoefficient);
+  }
+  
+
+  void
+  Sampler::interpolateTo (DataMap* dataMap, double interpolationCoefficient)
+  {
+    int pos = 0;
+    IndexMap* indices = dataMap->indexMap ();
+    for (IndexMap::iterator i = indices->begin ();
+	 i != indices->end ();
+	 ++i)
+      {
+	int localIndex = i->begin () - i->local ();
+	int iSize = i->end () - i->begin ();
+	if (dataMap->type () == MPI::DOUBLE)
+	  interpolate (pos, iSize, interpolationCoefficient,
+		       static_cast<double*> (dataMap->base ()) + localIndex);
+	else if (dataMap->type () == MPI::FLOAT)
+	  interpolate (pos, iSize, interpolationCoefficient,
+		       static_cast<float*> (dataMap->base ()) + localIndex);
+	else
+	  error ("internal error in Sampler::interpolateTo");
+	pos += iSize;
+      }    
+  }
+
+
+  void
+  Sampler::interpolate (int from,
+			int n,
+			double interpolationCoefficient,
+			double* dest)
+  {
+    MUSIC_LOGR ("interpolate to dest = " << static_cast<void*> (dest)
+		<< ", begin = " << from
+		<< ", length = " << n);
+    double* prev = (static_cast<double*> (static_cast<void*> (prevSample_))
+		    + from);
+    double* succ = (static_cast<double*> (static_cast<void*> (sample_))
+		    + from);
+    for (int i = 0; i < n; ++i)
+      dest[i] = ((1.0 - interpolationCoefficient) * prev[i]
+		 + interpolationCoefficient * succ[i]);
+  }
+			
+  
+  void
+  Sampler::interpolate (int from,
+			int n,
+			float interpolationCoefficient,
+			float* dest)
+  {
+    float* prev = (static_cast<float*> (static_cast<void*> (prevSample_))
+		    + from);
+    float* succ = (static_cast<float*> (static_cast<void*> (sample_))
+		    + from);
+    for (int i = 0; i < n; ++i)
+      dest[i] = ((1.0 - interpolationCoefficient) * prev[i]
+		 + interpolationCoefficient * succ[i]);
+  }
+			
+  
+}
+#endif
diff --git a/src/scheduler.cc b/src/scheduler.cc
new file mode 100644
index 0000000..165a3e1
--- /dev/null
+++ b/src/scheduler.cc
@@ -0,0 +1,644 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2012 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//#define MUSIC_DEBUG
+#include "music/scheduler.hh"
+#include "music/scheduler_agent.hh"
+
+#include "music/debug.hh"
+
+#if MUSIC_USE_MPI
+
+#include <cmath>
+#include <iostream>
+#include <set>
+#include <climits>
+
+#ifdef MUSIC_DEBUG
+#include <cstdlib>
+#endif
+
+namespace MUSIC
+{
+
+  Scheduler::Scheduler (MPI::Intracomm comm, int leader) :
+      nodes (NULL), appl_data_ (NULL), conn_data_ (NULL)
+  {
+    comm_ = comm;
+    leader_ = leader;
+  }
+
+
+  Scheduler::~Scheduler ()
+  {
+    if (nodes != NULL)
+      delete nodes;
+    if (appl_data_ != NULL)
+      delete[] appl_data_;
+    if (conn_data_ != NULL)
+      delete[] conn_data_;
+  }
+
+
+  void
+  Scheduler::initialize (TemporalNegotiatorGraph *appl_graph,
+      std::vector<Connector*>& connectors)
+  {
+
+    nodes = new SGraph (appl_graph->local_node_color (), appl_graph->nNodes (),
+        appl_graph->getNConnections ());
+
+    setApplications (appl_graph);
+
+    setConnections (appl_graph, connectors);
+
+    color_ = appl_graph->local_node_color ();
+
+    iter_node = nodes->begin ();
+    iter_conn = 0;
+
+    pushForward ();
+
+    std::vector<SchedulerAgent *>::iterator agent;
+    for (agent = agents_.begin(); agent != agents_.end(); agent++)
+      (*agent)->initialize(connectors);
+
+    initializeAgentState ();
+
+  }
+
+
+  void
+  Scheduler::setAgent (SchedulerAgent* agent)
+  {
+    agents_.push_back (agent);
+  }
+
+
+  void
+  Scheduler::initializeAgentState ()
+  {
+    cur_agent_ = agents_.begin ();
+  }
+
+
+  AEdge<Scheduler::SApplData, Scheduler::SConnData>
+  Scheduler::pushForward ()
+  {
+    while (true)
+      {
+#if 0
+        //	std::vector<Node*>::iterator node;
+        for (; iter_node < nodes.size (); ++iter_node )
+          {
+            Node *node = nodes.at(iter_node);
+            if (iter_conn < 0 && node->nextReceive () > node->localTime ().time ())
+            node->advance ();
+
+            std::vector<SConnection*>* conns = node->outputConnections ();
+            // std::vector<SConnection*>::iterator conn;
+
+            for (++iter_conn;
+                iter_conn < static_cast<int> (conns->size ());
+                ++iter_conn)
+              {
+                SConnection *conn = conns->at(iter_conn);
+                //do we have data ready to be sent?
+                if (conn->nextSend () <= conn->preNode ()->localTime ()
+                    && conn->nextReceive () == conn->postNode ()->localTime ())
+                  {
+                    SConnection sconn = *conn;
+                    sconn.postponeNextSend( conn->preNode()->localTime());
+                    conn->advance();
+                    return sconn;
+                  }
+              }
+            iter_conn = -1;
+          }
+#endif
+        for (; iter_node < nodes->end (); iter_node++)
+          {
+            if (iter_conn == 0)
+              iter_conn = (*iter_node).begin_o ();
+            else
+              {
+                advanceConnection ( (**iter_conn).data ());
+                ++iter_conn;
+              }
+            for (; iter_conn < (*iter_node).end_o (); iter_conn++)
+              {
+
+                //do we have data ready to be sent?
+                if ( (*iter_conn)->data ().nextSend
+                    <= (*iter_conn)->pre ().data ().localTime
+                    && (*iter_conn)->data ().nextReceive
+                        == (*iter_conn)->post ().data ().localTime)
+                  {
+                    last_sconn_ = * (*iter_conn);
+
+                    last_sconn_.data ().postponeNextSend (
+                        (*iter_conn)->pre ().data ().localTime);
+
+                    return last_sconn_;
+                  }
+              }
+
+            iter_conn = 0;
+          }
+
+
+        for (iter_node = nodes->begin (); iter_node < nodes->end ();
+            iter_node++)
+          {
+            Clock next_recv = nextApplicationReceive (*iter_node);
+            if ((*iter_node).data ().localTime < next_recv)
+              (*iter_node).data ().localTime.tick ();
+          }
+        iter_node = nodes->begin ();
+
+      }
+  }
+
+#if 0
+  void
+  Scheduler::createMultiConnectors (Clock localTime,
+      std::vector<Connector*>& connectors,
+      MultiBuffer* multiBuffer,
+      std::vector<MultiConnector*>& multiConnectors)
+    {
+      //if (MPI::COMM_WORLD.Get_rank () == 2)
+      //  std::cout << "prep localTime = " << localTime.time () << std::endl;
+      // We need to create the MultiConnectors ahead of time since their
+      // creation requires communication between all members of
+      // COMM_WORLD.  Temporary solution: Create all MultiConnectors
+      // that will be needed during the first 100 steps.
+      std::vector<std::pair<double, Connector *> > schedule;
+
+      std::vector<bool> multiProxies;
+      multiProxies.resize (Connector::proxyIdRange ());
+
+      for (int self_node = 0; self_node < (int) nodes.size (); ++self_node)
+        {
+          localTime.reset ();
+
+          createMultiConnNext (self_node,
+              localTime,
+              connectors,
+              multiBuffer,
+              schedule);
+
+          localTime.ticks (-1);
+
+          std::vector<Connector*> cCache;
+          for (int i = 0; i < 100; ++i)
+            {
+              localTime.tick ();
+              createMultiConnStep (self_node,
+                  localTime,
+                  connectors,
+                  multiBuffer,
+                  multiConnectors,
+                  multiProxies,
+                  cCache,
+                  schedule,
+                  false);
+            }
+          createMultiConnStep (self_node,
+              localTime,
+              connectors,
+              multiBuffer,
+              multiConnectors,
+              multiProxies,
+              cCache,
+              schedule,
+              true);
+          schedule.clear ();
+
+          // Now reset node and connection clocks to starting values
+          for (std::vector<Node*>::iterator node = nodes.begin ();
+              node != nodes.end ();
+              ++node)
+          (*node).localTime.reset ();
+
+          for (std::vector<SConnection*>::iterator conn = connections.begin ();
+              conn != connections.end ();
+              ++conn)
+            {
+              (*conn)->resetClocks ();
+              (*conn)->advance ();
+            }
+        }
+    }
+
+  void
+  Scheduler::createMultiConnNext (int self_node,
+      Clock& localTime,
+      std::vector<Connector*>& connectors,
+      MultiBuffer* multiBuffer_,
+      std::vector<std::pair<double, Connector *> > &schedule)
+    {
+      while (schedule.empty ()
+          // always plan forward past the first time point to make
+          // sure that all events at that time are scheduled
+          || schedule.front ().first == schedule.back ().first)
+        {
+          std::vector<Node*>::iterator node;
+          for ( node=nodes.begin (); node < nodes.end (); ++node )
+            {
+              if ((*node)->nextReceive () > (*node)->localTime ().time ())
+              (*node)->advance ();
+
+              std::vector<SConnection*>* conns = (*node)->outputConnections ();
+              std::vector<SConnection*>::iterator conn;
+              for (conn = conns->begin (); conn < conns->end (); ++conn)
+              //do we have data ready to be sent?
+              if ((*conn)->nextSend () <= (*conn)->preNode ()->localTime ()
+                  && (*conn)->nextReceive () == (*conn)->postNode ()->localTime ())
+                {
+                  if (self_node == (*conn)->postNode ()->getId () //input
+                      || self_node == (*conn)->preNode ()->getId ())//output
+                    {
+                      double nextComm
+                      = (self_node == (*conn)->postNode ()->getId ()
+                          ? (*conn)->postNode ()->localTime ().time ()
+                          : (*conn)->preNode ()->localTime ().time ());
+                      schedule.push_back
+                      (std::pair<double, Connector*>(nextComm,
+                              (*conn)->getConnector ()));
+                    }
+
+                  MUSIC_LOG0 ("Scheduled communication:"<< (*conn)->preNode ()->getId () <<"->"<< (*conn)->postNode ()->getId () << "at(" << (*conn)->preNode ()->localTime ().time () << ", "<< (*conn)->postNode ()->localTime ().time () <<")");
+                  (*conn)->advance ();
+                }
+            }
+        }
+    }
+
+  void
+  Scheduler::createMultiConnStep (int self_node,
+      Clock& localTime,
+      std::vector<Connector*>& connectors,
+      MultiBuffer* multiBuffer_,
+      std::vector<MultiConnector*>& multiConnectors,
+      std::vector<bool>& multiProxies,
+      std::vector<Connector*>& cCache,
+      std::vector<std::pair<double, Connector *> > &schedule,
+      bool finalize)
+    {
+      std::set<int>* connsToFinalize;
+      int finalCount = 0;
+
+      if (finalize)
+        {
+          connsToFinalize = new std::set<int>;
+          for (std::vector<Connector*>::iterator c = connectors.begin ();
+              c != connectors.end ();
+              ++c)
+          connsToFinalize->insert ((*c)->receiverPortCode ());
+        }
+
+      while (schedule[0].first <= localTime.time()
+          || (finalize && //!connsToFinalize->empty ()
+              ++finalCount <= 4000))
+        {
+          std::vector< std::pair<double, Connector*> >::iterator comm;
+          for (comm = schedule.begin ();
+              comm != schedule.end() && comm->first <= localTime.time ();
+              ++comm)
+            {
+              Connector* connector = comm->second;
+
+              if (connector == NULL)
+              continue;
+
+              if (finalize)
+              connsToFinalize->erase (connector->receiverPortCode ());
+
+              if (!connector->idFlag ())
+              continue;
+
+              unsigned int multiId = 0;
+              unsigned int multiProxyId = 0;
+              if (!connector->isProxy ())
+                {
+                  multiId = connector->idFlag ();
+                  cCache.push_back (connector);
+                }
+              else
+                {
+                  dynamic_cast<ProxyConnector*> (connector)->setNode (self_node);
+                  multiProxyId = connector->idFlag ();
+                }
+              bool isProxy = connector->isProxy ();
+              int remoteLeader = connector->remoteLeader ();
+              bool direction = connector->isInput ();
+              // yes, horrible quadratic algorithm for now
+              for (std::vector< std::pair<double, Connector*> >::iterator c
+                  = comm + 1;
+                  c != schedule.end () && c->first <= localTime.time();
+                  ++c)
+                {
+                  if (c->second == NULL || c->second->idFlag () == 0)
+                  continue;
+                  if (c->second->isProxy ())
+                  dynamic_cast<ProxyConnector*> (c->second)->setNode (self_node);
+                  // lumping criterion
+                  if (!(c->second->isProxy () ^ isProxy)
+                      && c->second->remoteLeader () == remoteLeader
+                      && c->second->isInput () == direction)
+                    {
+                      if (finalize)
+                      connsToFinalize->erase (c->second->receiverPortCode ());
+                      if (!c->second->isProxy ())
+                        {
+                          cCache.push_back (c->second);
+                          multiId |= c->second->idFlag ();
+                        }
+                      else
+                        {
+                          multiProxyId |= c->second->idFlag ();
+                        }
+                      c->second = NULL; // taken
+                    }
+                }
+
+              //if (MPI::COMM_WORLD.Get_rank () == 2)
+              //	std::cout << "Prep multiId = " << multiId << std::endl;
+              if (cCache.size () == 0)
+                {
+                  if (!multiProxies[multiProxyId])
+                    {
+                      std::cout << "Rank " << MPI::COMM_WORLD.Get_rank ()
+                      << ": *" << std::endl << std::flush;
+                      MPI::COMM_WORLD.Create (MPI::GROUP_EMPTY);
+                      MPI::COMM_WORLD.Barrier ();
+                      //*fixme* Impossible to delete the following object
+                      multiProxies[multiProxyId] = true;
+                    }
+                }
+              else if (multiConnectors[multiId] == NULL)
+                {
+                  multiConnectors[multiId]
+                  = new MultiConnector (multiBuffer_, cCache);
+                }
+              cCache.clear ();
+            }
+          schedule.erase (schedule.begin (), comm);
+          createMultiConnNext (self_node,
+              localTime,
+              connectors,
+              multiBuffer_,
+              schedule);
+        }
+
+      if (finalize)
+      delete connsToFinalize;
+
+    }
+#endif
+
+
+  void
+  Scheduler::reset (int color)
+  {
+    if (color < 0)
+      color = nodes->local_node_color ();
+    color_ = color;
+    reset ();
+    nodes->setTempColor (color);
+    std::vector<SConnection> path;
+    nodes->depthFirst (nodes->at (color), path);
+
+    cur_agent_ = agents_.begin ();
+    iter_node = nodes->begin ();
+    iter_conn = 0;
+    pushForward ();
+
+  }
+
+
+  void
+  Scheduler::reset ()
+  {
+    nodes->reset ();
+    for (SGraph::iterator n = nodes->begin (); n < nodes->end (); n++)
+      {
+        (*n).data ().localTime.reset ();
+        for (SNode::edge_iterator e = (*n).begin_o (); e < (*n).end_o (); e++)
+          {
+            (*e)->data ().reset ();
+            advanceConnection ( (**e).data ());
+          }
+      }
+  }
+
+
+  void
+  Scheduler::tick (Clock& localTime)
+  {
+    // tick is done when at least one of the agent will schedule the future communication
+    // next tick will start from the last successful agent
+    // this algorithm is based on temporally ordered SConnections
+    bool done = false;
+
+    for (; !done; cur_agent_++)
+      {
+        if (cur_agent_ == agents_.end ())
+          cur_agent_ = agents_.begin ();
+
+        if ( (*cur_agent_)->tick (localTime))
+          done = true;
+      }
+  }
+
+
+  void
+  Scheduler::finalize (Clock& localTime, std::vector<Connector*>& connectors)
+  {
+    /* remedius
+     * set of receiver port codes that still has to be finalized
+     */
+
+    std::set<int> cnn_ports;
+    for (std::vector<Connector*>::iterator c = connectors.begin ();
+        c != connectors.end (); ++c)
+#if 0
+      if (! (*c)->needsMultiCommunication ())
+#endif
+        {
+          cnn_ports.insert ( (*c)->receiverPortCode ());
+        }
+#if 0
+    for (std::vector<SchedulerAgent*>::iterator a = agents_.begin ();
+        a != agents_.end (); ++a)
+      (*a)->preFinalize (cnn_ports);
+#endif
+
+    for (; !cnn_ports.empty (); cur_agent_++)
+      {
+        if (cur_agent_ == agents_.end ())
+          cur_agent_ = agents_.begin ();
+        (*cur_agent_)->finalize (cnn_ports);
+      }
+  }
+
+
+  Clock
+  Scheduler::nextApplicationReceive (SNode &node)
+  {
+    SNode::edge_iterator in_conn;
+    Clock nextTime;
+    nextTime.set(ClockState(LLONG_MAX));
+    for (in_conn = node.begin_i (); in_conn < node.end_i (); ++in_conn)
+      {
+        SConnData &data = (*in_conn)->data ();
+        if (data.nextReceive < nextTime)
+          nextTime = data.nextReceive;
+      }
+    return nextTime;
+  }
+
+
+  void
+  Scheduler::advanceConnection (SConnData &data)
+  {
+    advanceConnectionClocks (data);
+    Clock r = data.nextReceive;
+    Clock s = data.nextSend;
+    advanceConnectionClocks (data);
+    while (data.nextReceive == r)
+      {
+        s = data.nextSend;
+        advanceConnectionClocks (data);
+      }
+    data.nextReceive = r;
+    data.nextSend = s;
+    MUSIC_LOG0 (pre_id << "->"<<post_id << "::"<<nextSend_.time () << "::" << nextReceive_.time ());
+  }
+
+
+  void
+  Scheduler::advanceConnectionClocks (SConnData &data)
+  {
+    ClockState limit = (data.nextSend.integerTime () + data.descr.accLatency
+        - data.nextReceive.tickInterval ());
+    while (data.nextReceive.integerTime () <= limit)
+      data.nextReceive.tick ();
+    data.nextSend.ticks (data.descr.maxBuffered + 1);
+  }
+
+
+  void
+  Scheduler::setApplications (TemporalNegotiatorGraph *appl_graph)
+  {
+    appl_data_ = new SApplData[appl_graph->nNodes ()];
+    int i = 0;
+    TemporalNegotiatorGraph::iterator it;
+    for (it = appl_graph->begin (); it < appl_graph->end (); ++it, ++i)
+      {
+        appl_data_[i].color = (*it).data ().color;
+        appl_data_[i].leader = (*it).data ().leader;
+        appl_data_[i].nProcs = (*it).data ().nProcs;
+        appl_data_[i].localTime.configure ( (*it).data ().timebase,
+            (*it).data ().tickInterval);
+        nodes->addNode (
+            SNode ( (*it).data ().nOutConnections, (*it).data ().nInConnections,
+                appl_data_[i]), (*it).data ().color);
+      }
+
+  }
+
+
+  void
+  Scheduler::setConnections (TemporalNegotiatorGraph *appl_graph,
+      std::vector<Connector*>& connectors)
+  {
+    conn_data_ = new SConnData[appl_graph->getNConnections ()];
+    int k = 0;
+    SGraph::iterator inode;
+    for (inode = nodes->begin (); inode < nodes->end (); inode++)
+      {
+        TemporalNegotiationData &data =
+            appl_graph->at ( (*inode).data ().color).data ();
+        for (int i = 0; i < data.nOutConnections; ++i)
+          {
+            Connector *connector;
+            bool foundLocalConnector = false;
+            ConnectionDescriptor &descr = data.connection[i];
+            SNode &pre = *inode;
+            SNode &post = nodes->at (descr.remoteNode);
+
+            for (std::vector<Connector*>::iterator c = connectors.begin ();
+                c != connectors.end (); ++c)
+              {
+                if (descr.receiverPort == (*c)->receiverPortCode ())
+                  {
+                    foundLocalConnector = true;
+                    connector = *c;
+                    (*c)->setInterpolate (descr.interpolate);
+                    (*c)->setLatency (descr.accLatency);
+                    (*c)->initialize ();
+                    break;
+                  }
+              }
+#if 1
+            if (!foundLocalConnector)
+              {
+                if (descr.multiComm)
+                  connector = new ProxyConnector (pre.data ().color,
+                      pre.data ().leader, pre.data ().nProcs,
+                      post.data ().color, post.data ().leader,
+                      post.data ().nProcs);
+                else
+                  connector = new ProxyConnector ();
+              }
+
+#endif
+            conn_data_[k].descr = descr;
+            conn_data_[k].connector = connector;
+            conn_data_[k].nextSend.configure (pre.data ().localTime.timebase (),
+                pre.data ().localTime.tickInterval ());
+            conn_data_[k].nextReceive.configure (
+                post.data ().localTime.timebase (),
+                post.data ().localTime.tickInterval ());
+            SConnection &edge = nodes->addEdge (
+                SConnection (pre, post, conn_data_[k++]));
+
+            advanceConnection (edge.data ());
+
+          }
+      }
+
+  }
+
+
+  void
+  Scheduler::SGraph::handleLoop (SNode &x, std::vector<SConnection> & path)
+  {
+    if (&x == &nodes_[tmp_color_])
+      {
+        // Mark connections on path as loop connected to self_node
+        for (std::vector<SConnection>::iterator c = path.begin ();
+            c != path.end (); ++c)
+          (*c).data ().isLoopConnected = true;
+      }
+  }
+
+}
+
+#endif
diff --git a/src/scheduler_agent.cc b/src/scheduler_agent.cc
new file mode 100644
index 0000000..b1d9a30
--- /dev/null
+++ b/src/scheduler_agent.cc
@@ -0,0 +1,543 @@
+#include <music/scheduler_agent.hh>
+
+//#define MUSIC_DEBUG
+#include "music/debug.hh"
+
+#if MUSIC_USE_MPI
+
+#include <algorithm>
+#include <iostream>
+#include <cassert>
+#ifdef MUSIC_DEBUG
+#include <cstdlib>
+#endif
+
+namespace MUSIC
+{
+  SchedulerAgent::SchedulerAgent (Scheduler *scheduler) :
+      scheduler_ (scheduler)
+  {
+
+  }
+
+
+  MulticommAgent::MulticommAgent (Scheduler *scheduler) :
+      SchedulerAgent (scheduler)
+  {
+    multiProxies = NULL;
+    multiBuffer_ = NULL;
+    filter1 = NULL;
+    filter2 = NULL;
+  }
+
+
+  MulticommAgent::Filter1::Filter1 (MulticommAgent &multCommObj) :
+      multCommObj_ (multCommObj)
+  {
+
+  }
+
+
+  /*    remedius
+   *  This filter is applied to the set of selected connectors in the fillSchedule().
+   *  It partitioned the set of connectors into two groups:
+   *  returns True: connectors that can be lumped:if scheduled send times <= multCommObj_.time_.
+   *  This condition is sufficient because each conflicting send time can be postponed to the most latter scheduled for the same node.
+   *  The most latter possible time is a multCommObj_.time_ (the receive time).
+   *  returns False: connectors that go to the Filter2 (connectors that possibly can be added to the current group)
+   */
+  bool
+  MulticommAgent::Filter1::operator() (SConnectionP &conn)
+  {
+    if (conn.second.sSend <= multCommObj_.time_)
+      {
+        int sId = conn.first.pre ().data ().color;
+        int rId = conn.first.post ().data ().color;
+        //keeps track of all receive nodes
+        multCommObj_.rNodes |= 1 << rId;
+        //guarantees that if there are both send and receive are scheduled to the same node,
+        // the receive time will be chosen.
+        multCommObj_.commTimes[rId] = multCommObj_.time_;
+        // take the most later time
+        if (conn.second.sSend >= multCommObj_.commTimes[sId])
+          multCommObj_.commTimes[sId] = conn.second.sSend;
+        return true;
+      }
+    return false;
+  }
+
+
+  MulticommAgent::Filter2::Filter2 (MulticommAgent &multCommObj) :
+      multCommObj_ (multCommObj)
+  {
+
+  }
+
+
+  /*    remedius
+   * This filter is applied to the rest of the selected connectors, that were classified as False by the Filter1.
+   * It adds those of the rest connectors(which scheduled send times > multCommObj_.time_.) that either don't have a conflict
+   * with the already selected connectors by Filter1 or if the conflict is solvable.
+   * The conflict is not solvable if both send and receive are scheduled for the same node.
+   */
+  bool
+  MulticommAgent::Filter2::operator() (SConnectionP &conn)
+  {
+    int sId = conn.first.pre ().data ().color;
+    int rId = conn.first.post ().data ().color;
+    std::map<int, Clock>::iterator it;
+    it = multCommObj_.commTimes.find (sId);
+    if (it == multCommObj_.commTimes.end ()
+        || ! (multCommObj_.rNodes & (1 << sId)))
+      {
+        multCommObj_.commTimes[sId] = conn.second.sSend;
+        multCommObj_.commTimes[rId] = multCommObj_.time_;
+        multCommObj_.rNodes |= 1 << rId;
+        return true;
+      }
+    return false;
+  }
+
+
+  MulticommAgent::~MulticommAgent ()
+  {
+    for (std::vector<MultiConnector*>::iterator connector =
+        multiConnectors.begin (); connector != multiConnectors.end ();
+        ++connector)
+      if (*connector != NULL)
+        delete *connector;
+    if (multiProxies != NULL)
+      delete multiProxies;
+    if (multiBuffer_ != NULL)
+      delete multiBuffer_;
+    if (filter1 != NULL)
+      delete filter1;
+    if (filter2 != NULL)
+      delete filter2;
+  }
+
+
+
+  void
+  MulticommAgent::initialize (std::vector<Connector*>& connectors)
+  {
+    filter1 = new Filter1 (*this);
+    filter2 = new Filter2 (*this);
+    multiBuffer_ = new MultiBuffer (scheduler_->comm(), scheduler_->getLeader(), connectors);
+    //contains the multiconnectors which were created (I'm included)
+    multiConnectors.resize (Connector::idRange ());
+    //denotes multiIds which were created (I'm not included)
+    multiProxies = new std::vector<bool>;
+    multiProxies->resize (Connector::proxyIdRange ());
+    for (unsigned int i = 0; i < Connector::idRange (); ++i)
+      multiConnectors[i] = NULL;
+    for (unsigned int i = 0; i < Connector::proxyIdRange (); ++i)
+      (*multiProxies)[i] = false;
+
+  }
+
+
+#if 0
+  void
+  MulticommAgent::createMultiConnectors (Clock& localTime, MPI::Intracomm comm,
+      int leader, std::vector<Connector*>& connectors)
+  {
+    multiBuffer_ = new MultiBuffer (comm, leader, connectors);
+    multiConnectors.resize (Connector::idRange ());
+    multiProxies = new std::vector<bool>;
+    multiProxies->resize (Connector::proxyIdRange ());
+
+    for (unsigned int self_node = 0; self_node < scheduler_->nApplications ();
+        ++self_node)
+      {
+
+        scheduler_->reset (self_node);
+
+        if (!create (localTime))
+          scheduler_->pushForward ();
+
+        localTime.ticks (-1);
+
+        for (int i = 0; i < N_PLANNING_CYCLES; ++i)
+          {
+            localTime.tick ();
+            if (!create (localTime))
+              scheduler_->pushForward ();
+
+          }
+
+        //finalize
+        schedule.clear ();
+
+        localTime.reset ();
+      }
+
+    scheduler_->reset (-1);
+    delete multiProxies;
+  }
+
+#endif
+
+  std::vector<Connector*>
+  MulticommAgent::connectorsFromMultiId (unsigned int multiId)
+  {
+    std::vector<Connector*> connectors;
+    for (unsigned int flag = 1; multiId != 0; flag <<= 1)
+      if (multiId & flag)
+        {
+          connectors.push_back (Connector::connectorFromIdFlag (flag));
+          multiId &= ~flag;
+        }
+    return connectors;
+  }
+
+#if 0
+  bool
+  MulticommAgent::create (MUSIC::Clock &localTime)
+  {
+    std::vector<MultiCommObject>::iterator comm;
+    bool continue_;
+    do
+      {
+        continue_ = fillSchedule ();
+        for (comm = schedule.begin ();
+            comm != schedule.end () && (*comm).time <= localTime;
+            ++comm)
+          {
+            unsigned int multiId = (*comm).multiId ();
+            if (multiId != 0)
+              {
+                if (multiConnectors[multiId] == NULL)
+                  {
+                    std::vector<Connector*> connectors = connectorsFromMultiId (
+                        multiId);
+                    multiConnectors[multiId] = new MultiConnector (multiBuffer_,
+                        connectors);
+                  }
+              }
+            else
+              {
+                unsigned int proxyId = (*comm).proxyId ();
+                if (proxyId != 0 && ! (*multiProxies)[proxyId])
+                  {
+                    //  std::cout << "Rank " << MPI::COMM_WORLD.Get_rank ()
+                    //      << ": Proxy " << proxyId << std::endl;
+                    MPI::COMM_WORLD.Create (MPI::GROUP_EMPTY);
+                    MPI::COMM_WORLD.Barrier ();
+                    (*multiProxies)[proxyId] = true;
+                  }
+              }
+          }
+        schedule.erase (schedule.begin (), comm);
+      }
+    while (continue_ && schedule.empty ());
+    return !schedule.empty ();
+  }
+
+#endif
+
+  bool
+  MulticommAgent::tick (MUSIC::Clock &localTime)
+  {
+    std::vector<MultiCommObject>::iterator comm;
+    bool continue_;
+    do
+      {
+        continue_ = fillSchedule ();
+        for (comm = schedule.begin ();
+            comm != schedule.end () && (*comm).time <= localTime; ++comm)
+          {
+            unsigned int multiId = (*comm).multiId ();
+            unsigned int proxyId = (*comm).proxyId ();
+            // if we participate in the multicommunication but the multiconnector was not yet created
+            if (multiId != 0 && multiConnectors[multiId] == NULL)
+              {
+                std::vector<Connector*> connectors = connectorsFromMultiId (
+                    multiId);
+                multiConnectors[multiId] = new MultiConnector (multiBuffer_,
+                    connectors);
+
+              }// if we do not participate in the multicommunication and the multiconnector was not yet created
+            else if (multiId == 0 && !((*multiProxies)[proxyId]))
+              {
+                MPI::COMM_WORLD.Create (MPI::GROUP_EMPTY);
+                MPI::COMM_WORLD.Barrier ();
+                (*multiProxies)[proxyId] = true;
+              }
+
+            if ( multiId != 0)
+              {
+                assert (multiConnectors[multiId] != NULL);
+                multiConnectors[multiId]->tick ();
+              }
+          }
+        schedule.erase (schedule.begin (), comm);
+        // we continue looping while:
+        // 1. we haven't found the communication from the future:   !schedule.empty()
+        // 2. or the next SConnection can't be processed by the current agent: continue_= false
+      }
+    while (continue_ && schedule.empty ());
+    return !schedule.empty ();
+  }
+
+
+  // *schedule object can be either non empty or empty
+  // if it's empty it will be filled with collective connectors if appropriate
+  // if it's non empty, it contains collective connectors filled in before
+  // *last_sconn can be either p2p or collective connector
+  bool
+  MulticommAgent::fillSchedule ()
+  {
+    if (!schedule.empty ())
+      return true;
+    Scheduler::SConnection last_sconn = scheduler_->getLastSConnection ();
+    if (!last_sconn.data ().connector->idFlag ())
+      return false;
+    Clock nextReceive = last_sconn.data ().nextReceive; //last connection
+    SConnectionPV nextSConnections;
+    do
+      {
+#if 0
+        if (last_sconn.data ().isLoopConnected
+            || scheduler_->isLocalConnection (last_sconn))
+#endif
+          nextSConnections.push_back (
+              std::make_pair (last_sconn, last_sconn.data ()));
+
+        last_sconn = scheduler_->pushForward ();
+      }
+    while (last_sconn.data ().connector->idFlag () //those that request multicommunication
+    && (last_sconn.data ().nextReceive == nextReceive)); //those that have scheduled receive at current time
+    //  || (!last_sconn.data ().isLoopConnected //
+    //  && !scheduler_->isLocalConnection (last_sconn))));
+
+    if (nextSConnections.size () > 0)
+      NextMultiConnection (nextSConnections);
+
+    return last_sconn.data ().connector->idFlag ();
+  }
+
+
+  void
+  MulticommAgent::NextMultiConnection (SConnectionPV &candidates)
+  {
+    time_ = candidates[0].second.nextReceive;
+    // std::map<int, Clock> prevCommTime;
+    SConnectionPV::iterator iter_bound = candidates.begin ();
+    SConnectionPV::iterator cur_bound = candidates.begin ();
+    do
+      {
+        cur_bound = iter_bound;
+
+        commTimes.clear ();
+        rNodes = 0;
+
+        // after the first iteration inner partitioning (Filter1) will always return .begin()
+        iter_bound = std::stable_partition (
+            std::stable_partition (cur_bound, candidates.end (), *filter1),
+            candidates.end (), *filter2);
+
+        //postpone sends in the multiconn for consistency
+        for (SConnectionPV::iterator it = cur_bound; it != iter_bound; ++it)
+          (*it).second.postponeNextSend (
+              commTimes[ (*it).first.pre ().data ().color]);
+
+        std::map<int, Clock>::iterator id_iter;
+        if ( (id_iter = commTimes.find (scheduler_->self_node ()))
+            != commTimes.end ())
+          scheduleMulticonn ( (*id_iter).second, cur_bound, iter_bound);
+      }
+    while (iter_bound != candidates.end ());
+  }
+
+
+  void
+  MulticommAgent::scheduleMulticonn (Clock &time, SConnectionPV::iterator first,
+      SConnectionPV::iterator last)
+  {
+    unsigned int multiId = 0;
+    unsigned int proxyId = 0;
+    MUSIC_LOGR ("SelfNode: " << scheduler_->self_node() << " Time: "<< time.time() << std::endl << "MultiConnector:");
+    for (SConnectionPV::iterator it = first; it != last;
+        ++it)
+      {
+        if ( (*it).second.connector->isProxy ())
+          proxyId |= (*it).second.connector->idFlag ();
+        else
+          multiId |= (*it).second.connector->idFlag ();
+        MUSIC_LOGR ("("<< (*it).preNode ()->getId () <<" -> "<< (*it).postNode ()->getId () << ") at " << (*it).nextSend().time () << " -> "<< (*it).nextReceive ().time ());
+      }
+    schedule.push_back (MultiCommObject (time,  multiId , proxyId));
+  }
+
+#if 0
+  void
+  MulticommAgent::preFinalize (std::set<int> &cnn_ports)
+  {
+    for (std::vector<MultiConnector*>::iterator m = multiConnectors.begin ();
+        m != multiConnectors.end (); ++m)
+      if (*m != NULL)
+        cnn_ports.insert ( (*m)->connectorCode ());
+  }
+#endif
+
+  void
+  MulticommAgent::finalize (std::set<int> &cnn_ports)
+  {
+    std::vector<MultiCommObject>::iterator comm;
+    bool continue_;
+    do
+      {
+        continue_ = fillSchedule ();
+        for (comm = schedule.begin ();
+            comm != schedule.end () && !cnn_ports.empty (); ++comm)
+          {
+            unsigned int multiId = (*comm).multiId ();
+            unsigned int proxyId = (*comm).proxyId ();
+            // if we participate in the multicommunication but the multiconnector was not yet created
+            if (multiId != 0 && multiConnectors[multiId] == NULL)
+              {
+                std::vector<Connector*> connectors = connectorsFromMultiId (
+                    multiId);
+                multiConnectors[multiId] = new MultiConnector (multiBuffer_,
+                    connectors);
+              } // if we do not participate in the multicommunication and the multiconnector was not yet created
+            else if (multiId == 0 && ! ( (*multiProxies)[proxyId]))
+              {
+
+                MPI::COMM_WORLD.Create (MPI::GROUP_EMPTY);
+                MPI::COMM_WORLD.Barrier ();
+                (*multiProxies)[proxyId] = true;
+
+              }
+            if (multiId != 0)
+              {
+                MultiConnector* m = multiConnectors[multiId];
+#if 0
+                if (cnn_ports.find (m->connectorCode ()) == cnn_ports.end ())
+                  continue;
+#endif
+                if (m->isFinalized ())
+                // an output port was finalized in tick ()
+                  {
+#if 0
+                    cnn_ports.erase (m->connectorCode ());
+#endif
+                    std::vector<Connector*> conns = connectorsFromMultiId (multiId);
+                    std::vector<Connector *>::iterator it;
+                    for(it = conns.begin(); it != conns.end(); ++it)
+                      cnn_ports.erase ((*it)->receiverPortCode());
+                    continue;
+#if 0
+                    // Sometimes the scheduler fails to generate all
+                    // multiConnectors during finalization.  Here, we
+                    // weed out multiConnectors that were finalized as
+                    // a consequence of the finalization of m.
+                    for (std::vector<MultiConnector*>::iterator m =
+                        multiConnectors.begin (); m != multiConnectors.end ();
+                        ++m)
+                      if (*m != NULL
+                          && (cnn_ports.find ( (*m)->connectorCode ())
+                              != cnn_ports.end ()) && (*m)->isFinalized ())
+                        cnn_ports.erase ( (*m)->connectorCode ());
+                    continue;
+#endif
+                  }
+                // finalize () needs to come after isFinalized check
+                // since it can itself set finalized state
+                m->finalize ();
+
+                m->tick ();
+              }
+          }
+        schedule.clear ();
+      }
+    while (continue_ && !cnn_ports.empty ());
+  }
+
+
+  UnicommAgent::UnicommAgent (Scheduler *scheduler) :
+      SchedulerAgent (scheduler)
+  {
+  }
+
+
+  // *schedule object can be either non empty or empty
+  // if it's empty it will be filled with p2p connector if appropriate
+  // if it's non empty, it contains p2p connectors filled in before
+  // *last_sconn can be either p2p or collective connector
+  bool
+  UnicommAgent::fillSchedule ()
+  {
+    if (!schedule.empty ())
+      return true;
+    Scheduler::SConnection last_sconn = scheduler_->getLastSConnection ();
+    if (last_sconn.data ().connector->idFlag ())
+      return false;
+    if (scheduler_->isLocalConnection (last_sconn))
+      {
+        Clock nextComm = (
+            scheduler_->self_node () == last_sconn.post ().data ().color ?
+                last_sconn.data ().nextReceive :
+                last_sconn.data ().nextSend);
+        schedule.time = nextComm;
+        schedule.connector = last_sconn.data ().connector;
+        MUSIC_LOGR (" :Scheduled communication:"<< last_sconn.preNode ()->getId () <<"->"
+            << last_sconn.postNode ()->getId ()<< "at("
+            << last_sconn.nextSend ().time () << ", "
+            << last_sconn.nextReceive ().time () <<")");
+
+      }
+    scheduler_->pushForward ();
+    return true;
+  }
+
+
+  bool
+  UnicommAgent::tick (Clock& localTime)
+  {
+    bool continue_;
+    do
+      {
+        continue_ = fillSchedule ();
+        if (!schedule.empty () && schedule.time <= localTime)
+          {
+            schedule.connector->tick ();
+            schedule.reset ();
+          }
+      }
+    while (continue_ && schedule.empty ());
+    return !schedule.empty ();
+  }
+
+
+  void
+  UnicommAgent::finalize (std::set<int> &cnn_ports)
+  {
+    bool continue_;
+    do
+      {
+        continue_ = fillSchedule ();
+        if (!schedule.empty ())
+          {
+            Connector* connector = schedule.connector;
+            schedule.reset ();
+            if ( (cnn_ports.find (connector->receiverPortCode ())
+                == cnn_ports.end ()))
+              continue;
+            if (connector->isFinalized ())
+            // an output port was finalized in tick ()
+              {
+                cnn_ports.erase (connector->receiverPortCode ());
+                continue;
+              }
+            // finalize () needs to come after isFinalized check
+            // since it can itself set finalized state
+            connector->finalize ();
+          }
+      }
+    while (continue_ && !cnn_ports.empty ());
+  }
+
+}
+#endif
diff --git a/src/setup.cc b/src/setup.cc
new file mode 100644
index 0000000..45422ef
--- /dev/null
+++ b/src/setup.cc
@@ -0,0 +1,459 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "music/setup.hh"
+#if MUSIC_USE_MPI
+#include <mpi.h>
+
+#include "music/runtime.hh"
+#include "music/parse.hh"
+#include "music/error.hh"
+#include "music/application_mapper.hh"
+#include <strings.h>
+#include <fstream>
+
+namespace MUSIC {
+
+  bool Setup::isInstantiated_ = false;
+  static std::string err_MPI_Init = "MPI_Init was called before the Setup constructor";
+  const char* const Setup::opConfigFileName = "--music-config";
+  const char* const Setup::opAppLabel = "--app-label";
+
+  Setup::Setup (int& argc, char**& argv)
+    : argc_ (argc), argv_ (argv)
+  {
+    checkInstantiatedOnce (isInstantiated_, "Setup");
+    if (MPI::Is_initialized ())
+      errorRank (err_MPI_Init);
+    maybeProcessMusicArgv (argc, argv);
+    MPI::Init (argc, argv);
+
+    init (argc, argv);
+
+  }
+
+  
+  Setup::Setup (int& argc, char**& argv, int required, int* provided)
+    : argc_ (argc), argv_ (argv)
+  {
+    checkInstantiatedOnce (isInstantiated_, "Setup");
+    if (MPI::Is_initialized ())
+      errorRank (err_MPI_Init);
+    maybeProcessMusicArgv (argc, argv);
+#ifdef HAVE_CXX_MPI_INIT_THREAD
+    *provided = MPI::Init_thread (argc, argv, required);
+#else
+    // Only C version provided in libmpich
+    MPI_Init_thread (&argc, &argv, required, provided);
+#endif
+    init (argc, argv);
+  }
+
+
+  Setup::~Setup ()
+    {
+      for (std::vector<Port*>::iterator i = ports_.begin ();
+           i != ports_.end ();
+           ++i)
+        (*i)->setupCleanup ();
+
+      if (launchedByMusic ())
+        delete temporalNegotiator_;
+
+      // delete connection objects
+      for (std::vector<Connection*>::iterator i = connections_->begin ();
+           i != connections_->end ();
+           ++i)
+        delete *i;
+
+      delete connections_;
+
+      delete config_;
+
+      isInstantiated_ = false;
+    }
+
+
+  void
+  Setup::init (int& argc, char**& argv)
+  {
+    int myRank = MPI::COMM_WORLD.Get_rank ();
+    std::string config = "";
+    launchedByMusic_ = false;
+    postponeSetup_ = false;
+
+    if (launchedWithExec (config))
+      {
+        assert(config.length() > 0);
+        launchedByMusic_ = true;
+        if (!config.compare (0, 8, "POSTPONE"))
+          postponeSetup_ = true;
+        config_ = new Configuration (config);
+      }
+    else if (launchedMPMD (argc, argv, config))
+      {
+        launchedByMusic_ = true;
+        std::string config_file;
+        loadConfigFile (config, config_file);
+
+        std::string app_label;
+        std::string binary (argv[0]);
+        // argv[0] is the name of the program,
+        // or an empty string if the name is not available
+        if (!getOption (argc, argv, opAppLabel, app_label)
+            && binary.length () == 0)
+          {
+            std::ostringstream oss;
+            oss << "MUSIC: use --app-label to specify application label";
+            error0 (oss.str ());
+          }
+
+        std::istringstream config_istream (config_file);
+        config_ = new Configuration ();
+        ApplicationMapper app_mapper(config_);
+        app_mapper.map(&config_istream, binary, app_label);
+      }
+    else
+      config_ = new Configuration ();
+
+
+    connections_ = new std::vector<Connection*>; // destroyed by runtime
+    if (launchedByMusic ())
+      {
+        // launched by the music utility
+        if (!postponeSetup_)
+          {
+            fullInit ();
+            argc = argc_;
+            argv = argv_;
+          }
+        comm = MPI::COMM_WORLD.Split (config_->Color (), myRank);
+      }
+    else
+      {
+        // launched with mpirun
+        comm = MPI::COMM_WORLD;
+        timebase_ = MUSIC_DEFAULT_TIMEBASE;
+      }
+  }
+
+
+  bool
+  Setup::getOption (int argc, char** argv, std::string option, std::string& result)
+  {
+    result.assign("");
+    for (int i = 1; i < argc; ++i)
+       if (option.compare(argv[i]) == 0 && argc > i){
+           result.assign(argv[i+1]);  // skip options
+             return true;
+       }
+     return false;
+  }
+
+
+  bool
+  Setup::launchedWithExec (std::string &result)
+  {
+    // is _MUSIC_CONFIG_ env variable is set ?
+    char* res = getenv (Configuration::configEnvVarName);
+    if (res != NULL)
+      {
+        result.assign (res);
+        return true;
+      }
+    else
+      return false;
+  }
+
+
+  bool
+  Setup::launchedMPMD (int argc, char** argv, std::string& config)
+  {
+    // if given option --music-config,
+    // the launch is categorized as MPMD
+    if (!getOption(argc, argv, opConfigFileName, config) )
+      return false;
+    else
+      return true;
+  }
+
+
+  void
+  Setup::loadConfigFile (std::string filename, std::string &result)
+  {
+    std::ifstream config;
+    char* buffer;
+    int size = 0;
+    int myRank = MPI::COMM_WORLD.Get_rank ();
+    // Rank #0 is reading a file and broadcast it to each rank in the launch
+    if (myRank == 0)
+      {
+        config.open (filename.c_str ());
+        if (!config.is_open ())
+          {
+            std::ostringstream oss;
+            oss << "MUSIC: Couldn't open configuration file: " << filename;
+            error0 (oss.str ());
+          }
+
+        size = config.tellg ();
+        config.seekg (0, std::ios_base::end);
+        long cur_pos = config.tellg ();
+        size = cur_pos - size;
+        config.seekg (0, std::ios_base::beg);
+      }
+    // first broadcast the size of the file
+    MPI::COMM_WORLD.Bcast (&size, 1, MPI::INT, 0);
+    buffer = new char[size];
+
+    if (myRank == 0)
+      config.read (buffer, size);
+    // then broadcast the file but itself
+    MPI::COMM_WORLD.Bcast (buffer, size, MPI::BYTE, 0);
+    // parseMapFile (app_name, std::string (buffer, size), result);
+    if (myRank == 0)
+      config.close ();
+
+    result.assign (buffer);
+    delete[] buffer;
+  }
+
+
+  void
+  Setup::maybeProcessMusicArgv (int& argc, char**& argv)
+  {
+    char* MUSIC_ARGV = getenv ("MUSIC_ARGV");
+    if (MUSIC_ARGV != NULL)
+      {
+	std::string cmd;
+	std::string argstring;
+	char* s = index (MUSIC_ARGV, ' ');
+	if (s == NULL)
+	  {
+	    cmd = std::string (MUSIC_ARGV);
+	    argstring = "";
+	  }
+	else
+	  {
+	    cmd = std::string (MUSIC_ARGV, s - MUSIC_ARGV);
+	    argstring = std::string (s + 1);
+	  }
+	char** newArgv = parseArgs (cmd, argstring, &argc);
+	for (int i = 0; i < argc; ++i)
+	  argv[i] = newArgv[i];
+	delete[] newArgv;
+      }
+  }
+
+
+  void
+  Setup::maybePostponedSetup ()
+  {
+    if (postponeSetup_)
+      {
+	delete config_;
+	config_ = new Configuration ();
+	fullInit ();
+      }
+  }
+
+
+  void
+  Setup::errorChecks ()
+  {
+    ApplicationMap* apps = applicationMap ();
+    int nRequestedProc = apps->nProcesses ();
+    int nMPIProc = MPI::COMM_WORLD.Get_size ();
+    if (nMPIProc != nRequestedProc)
+      {
+	std::ostringstream msg;
+	msg << "configuration file specifies " << nRequestedProc
+	    << " MPI processes but MUSIC was given " << nMPIProc
+	    << std::endl;
+	error0 (msg.str ());
+      }
+  }
+
+
+  void
+  Setup::fullInit ()
+  {
+    errorChecks ();
+    if (!config ("timebase", &timebase_))
+      timebase_ = MUSIC_DEFAULT_TIMEBASE;	       // default timebase
+    string binary;
+    config_->lookup ("binary", &binary);
+    string args;
+    config_->lookup ("args", &args);
+    argv_ = parseArgs (binary, args, &argc_);
+    temporalNegotiator_ = new TemporalNegotiator (this);
+  }
+  
+
+  bool
+  Setup::launchedByMusic ()
+  {
+    return launchedByMusic_;
+  }
+
+  
+  MPI::Intracomm
+  Setup::communicator ()
+  {
+    return comm;
+  }
+
+
+  ConnectivityInfo*
+  Setup::portConnectivity (const std::string localName)
+  {
+    return config_->connectivityMap ()->info (localName);
+  }
+
+
+  ApplicationMap*
+  Setup::applicationMap ()
+  {
+    return config_->applications ();
+  }
+
+
+  int
+  Setup::applicationColor ()
+  {
+	  return config_->Color();
+  }
+
+
+  std::string
+  Setup::applicationName()
+  {
+    return config_->Name();
+  }
+
+
+  int
+  Setup::leader ()
+  {
+    return config_->Leader ();
+  }
+
+
+  int
+  Setup::nProcs ()
+  {
+    return comm.Get_size ();
+  }
+
+
+  ConnectivityInfo::PortDirection
+  Setup::portDirection (const std::string localName)
+  {
+    return config_->connectivityMap ()->direction (localName);
+  }
+
+
+  int
+  Setup::portWidth (const std::string localName)
+  {
+    return config_->connectivityMap ()->width (localName);
+  }
+
+
+  PortConnectorInfo
+  Setup::portConnections (const std::string localName)
+  {
+    return config_->connectivityMap ()->connections (localName);
+  }
+
+
+  bool
+  Setup::config (string var, string* result)
+  {
+    return config_->lookup (var, result);
+  }
+
+  
+  bool
+  Setup::config (string var, int* result)
+  {
+    return config_->lookup (var, result);
+  }
+
+  
+  bool
+  Setup::config (string var, double* result)
+  {
+    return config_->lookup (var, result);
+  }
+
+  
+  ContInputPort*
+  Setup::publishContInput (std::string identifier)
+  {
+    return new ContInputPort (this, identifier);
+  }
+
+
+  ContOutputPort*
+  Setup::publishContOutput (std::string identifier)
+  {
+    return new ContOutputPort (this, identifier);
+  }
+
+
+  EventInputPort*
+  Setup::publishEventInput (std::string identifier)
+  {
+    return new EventInputPort (this, identifier);
+  }
+
+
+  EventOutputPort*
+  Setup::publishEventOutput (std::string identifier)
+  {
+    return new EventOutputPort (this, identifier);
+  }
+
+  
+  MessageInputPort*
+  Setup::publishMessageInput (std::string identifier)
+  {
+    return new MessageInputPort (this, identifier);
+  }
+
+
+  MessageOutputPort*
+  Setup::publishMessageOutput (std::string identifier)
+  {
+    return new MessageOutputPort (this, identifier);
+  }
+
+  
+  void Setup::addPort (Port* p)
+  {
+    ports_.push_back (p);
+  }
+
+  
+  void Setup::addConnection (Connection* c)
+  {
+    connections_->push_back (c);
+  }
+
+}
+#endif
diff --git a/src/spatial.cc b/src/spatial.cc
new file mode 100644
index 0000000..41d7e41
--- /dev/null
+++ b/src/spatial.cc
@@ -0,0 +1,604 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/spatial.hh" // Must be included first on BG/Ls
+
+#include "music/debug.hh"
+
+#if MUSIC_USE_MPI
+
+#include <sstream>
+
+#include "music/error.hh"
+#include "music/communication.hh"
+#include "music/connector.hh" // used only for debugging
+
+namespace MUSIC {
+
+  NegotiationIterator::BufferTraversal::BufferTraversal
+  (std::vector<NegotiationIntervals>& buffers_)
+    : buffers (buffers_), buffer (0), interval (0)
+  {
+    findInterval ();
+  }
+
+
+  void
+  NegotiationIterator::BufferTraversal::findInterval ()
+  {
+    while (buffer < buffers.size () && interval == buffers[buffer].size ())
+      {
+	// Check next buffer
+	++buffer;
+	interval = 0;
+      }
+  }
+  
+
+  bool
+  NegotiationIterator::BufferTraversal::end ()
+  {
+    return buffer == buffers.size ();
+  }
+
+
+  void
+  NegotiationIterator::BufferTraversal::operator++ ()
+  {
+    ++interval;
+    findInterval ();
+  }
+
+
+  SpatialNegotiationData*
+  NegotiationIterator::BufferTraversal::dereference ()
+  {
+    return &buffers[buffer][interval];
+  }
+
+
+  void
+  NegotiationIterator::init (Implementation* impl)
+  {
+    implementation_ = impl;
+    end_ = false;
+    ++*this;
+  }
+
+
+  NegotiationIterator::~NegotiationIterator ()
+  {
+    delete implementation_;
+  }
+
+  
+  NegotiationIterator::NegotiationIterator (const NegotiationIterator& i)
+    : implementation_ (i.implementation_->copy ()),
+      current_ (i.current_),
+      end_ (i.end_)
+  {
+  }
+
+  
+  const NegotiationIterator&
+  NegotiationIterator::operator= (const NegotiationIterator& i)
+  {
+    delete implementation_;
+    implementation_ = i.implementation_->copy ();
+    current_ = i.current_;
+    end_ = i.end_;
+    return *this;
+  }
+
+  
+  NegotiationIterator&
+  NegotiationIterator::operator++ ()
+  {
+    if (implementation_->end ())
+      end_ = true;
+    else
+      {
+	current_ = *implementation_->dereference ();
+	++*implementation_;
+	while (!implementation_->end ()
+	       && implementation_->dereference ()->begin () == current_.end ()
+	       && implementation_->dereference ()->local () == current_.local ()
+	       && implementation_->dereference ()->rank () == current_.rank ())
+	  {
+	    // join intervals
+	    current_.setEnd (implementation_->dereference ()->end ());
+	    ++*implementation_;
+	  }
+      }
+    return *this;
+  }
+
+  
+  SpatialNegotiationData*
+  NegotiationIterator::operator-> ()
+  {
+    return &current_;
+  }
+
+
+  SpatialNegotiator::SpatialNegotiator (IndexMap* ind, Index::Type type_, MPI::Intracomm c)
+  : comm(c), indices (ind), type (type_)
+  {
+
+	  nProcesses = comm.Get_size ();
+	  localRank = comm.Get_rank ();
+	  negotiateWidth ();
+
+  }
+
+
+
+  void
+  SpatialNegotiator::negotiateWidth ()
+  {
+
+    // First determine local least upper bound and width
+    int u = 0;
+    int w = 0;
+    for (IndexMap::iterator i = indices->begin ();
+	 i != indices->end ();
+	 ++i)
+      {
+	if (i->end () > u)
+	  u = i->end ();
+	w += i->end () - i->begin ();
+
+      }
+
+    // Now take maximum over all processes
+    std::vector<int> m (nProcesses);
+    comm.Allgather (&u, 1, MPI::INT, &m[0], 1, MPI::INT);
+    for (unsigned int i = 0; i < nProcesses; ++i)
+      if (m[i] > u)
+	u = m[i];
+    width = u;
+    comm.Allgather (&w, 1, MPI::INT, &m[0], 1, MPI::INT);
+    for (unsigned int i = 0; i < nProcesses; ++i)
+      if (m[i] > w)
+	w = m[i];
+
+    maxLocalWidth_ = w;
+
+
+  }
+
+
+  void
+  SpatialOutputNegotiator::negotiateWidth ()
+  {
+    if (localRank == 0)
+      {
+	// Receiver might need to know sender width
+	intercomm.Send (&width, 1, MPI::INT, 0, WIDTH_MSG);
+	int remoteWidth;
+	intercomm.Recv (&remoteWidth, 1, MPI::INT, 0, WIDTH_MSG);
+	if (remoteWidth != width)
+	  {
+	    std::ostringstream msg;
+	    msg << "sender and receiver width mismatch ("
+		<< width << " != " << remoteWidth << ")";
+	    error (msg.str ());
+	  }
+      }
+  }
+
+
+  void
+  SpatialInputNegotiator::negotiateWidth ()
+  {
+    if (localRank == 0)
+      {
+	int remoteWidth;
+	intercomm.Recv (&remoteWidth, 1, MPI::INT, 0, WIDTH_MSG);
+	// NOTE: For now, the handling of Index::WILDCARD_MAX is a bit
+	// incomplete since, if there is any index interval on the
+	// receiver side with index larger than the sender side width,
+	// we will still choose sender side width as receiver side
+	// width.
+	/* remedius
+	 * temporal fix is width = remoteWidth; shouldn't be like this!!!
+	 */
+	if (width == Index::WILDCARD_MAX || width < remoteWidth )
+	  width = remoteWidth;
+	intercomm.Send (&width, 1, MPI::INT, 0, WIDTH_MSG);
+      }
+    // Broadcast result (if we used a wildcard)
+    comm.Bcast (&width, 1, MPI::INT, 0);
+    if (maxLocalWidth_ == Index::WILDCARD_MAX)
+      maxLocalWidth_ = width;
+  }
+
+  
+  NegotiationIterator
+  SpatialNegotiator::canonicalDistribution (int width, int nProcesses)
+  {
+    class Wrapper : public NegotiationIterator::Implementation {
+      int i;
+      int r;
+      int w;
+      int nPerProcess;
+      SpatialNegotiationData data;
+    public:
+      Wrapper (int width, int nProcesses)
+	: i (0), r (0), w (width)
+      {
+	nPerProcess = w / nProcesses;
+	if (w % nProcesses > 0)
+	  ++nPerProcess;
+      }
+      bool end () { return i >= w; }
+      void operator++ () { ++r; i += nPerProcess; }
+      SpatialNegotiationData* dereference ()
+      {
+	int high = std::min (i + nPerProcess, w);
+	data = SpatialNegotiationData (IndexInterval (i, high, 0), r, 0);
+	return &data;
+      }
+      Implementation* copy ()
+      {
+	return new Wrapper (*this);
+      }
+    };
+
+    return NegotiationIterator (new Wrapper (width, nProcesses));
+  }
+
+  
+  NegotiationIterator
+  SpatialNegotiator::wrapIntervals (IndexMap::iterator beg,
+				    IndexMap::iterator end,
+				    Index::Type type,
+				    int rank)
+  {
+    class Wrapper : public NegotiationIterator::Implementation {
+    protected:
+      SpatialNegotiationData data;
+      IndexMap::iterator i;
+    private:
+      IndexMap::iterator end_;
+    protected:
+      int rank_;
+      int cur_displ_;
+    public:
+      Wrapper (IndexMap::iterator beg,
+	       IndexMap::iterator end,
+	       int rank)
+	: i (beg), end_ (end), rank_ (rank)
+      {
+    	  cur_displ_ = 0;
+      }
+      bool end () { return i == end_; }
+      void operator++ () {
+    	  cur_displ_ +=(i->end() - i->begin());
+      ++i;
+      if(end())
+    	  cur_displ_ = 0;}
+    };
+
+    class GlobalWrapper : public Wrapper {
+    public:
+      GlobalWrapper (IndexMap::iterator beg,
+		     IndexMap::iterator end,
+		     int rank)
+	: Wrapper (beg, end, rank)
+      {
+      }
+      SpatialNegotiationData* dereference ()
+      {
+	data = SpatialNegotiationData (*i, rank_, cur_displ_);
+	data.setLocal (0);
+	return &data;
+      }
+      Implementation* copy ()
+      {
+	return new GlobalWrapper (*this);
+      }
+    };
+  
+    class LocalWrapper : public Wrapper {
+    public:
+      LocalWrapper (IndexMap::iterator beg,
+		    IndexMap::iterator end,
+		    int rank)
+	: Wrapper (beg, end, rank)
+      {
+      }
+      SpatialNegotiationData* dereference ()
+      {
+	data = SpatialNegotiationData (*i, rank_, cur_displ_);
+	return &data;
+      }
+      Implementation* copy ()
+      {
+	return new LocalWrapper (*this);
+      }
+    };
+  
+    Wrapper* w;
+    if (type == Index::GLOBAL)
+      w = new GlobalWrapper (beg, end, rank);
+    else
+      w = new LocalWrapper (beg, end, rank);
+    return NegotiationIterator (w);
+  }
+
+  
+  // Compute intersection intervals between source and dest.  Store
+  // the resulting intervals with rank from source in buffer
+  // belonging to rank in dest.
+  void
+  SpatialNegotiator::intersectToBuffers
+  (std::vector<NegotiationIntervals>& source,
+   std::vector<NegotiationIntervals>& dest,
+   std::vector<NegotiationIntervals>& buffers)
+  {
+    // Cleanup old buffer content
+    for (std::vector<NegotiationIntervals>::iterator i = buffers.begin ();
+	 i != buffers.end ();
+	 ++i)
+      i->clear ();
+    for (std::vector<NegotiationIntervals>::iterator d = dest.begin ();
+	 d != dest.end ();
+	 ++d)
+      for (std::vector<NegotiationIntervals>::iterator s = source.begin ();
+	   s != source.end ();
+	   ++s)
+	intersectToBuffers2 (*s, *d, buffers);
+  }
+
+  
+  void
+  SpatialNegotiator::intersectToBuffers
+  (NegotiationIterator source,
+   NegotiationIterator dest,
+   std::vector<NegotiationIntervals>& buffers)
+  {
+    // Cleanup old buffer content
+    for (std::vector<NegotiationIntervals>::iterator i = buffers.begin ();
+	 i != buffers.end ();
+	 ++i)
+      i->clear ();
+    intersectToBuffers2 (source, dest, buffers);
+  }
+    
+    
+  void
+  SpatialNegotiator::intersectToBuffers2
+  (NegotiationIterator source,
+   NegotiationIterator dest,
+   std::vector<NegotiationIntervals>& buffers)
+  {
+    while (!source.end () && !dest.end ())
+      {
+	MUSIC_LOGX("(" << source->begin () << ", "
+		    << source->end () << ", "
+		    << source->local () << ", "
+		    << source->rank () << ") and ("
+		    << dest->begin () << ", "
+		    << dest->end () << ", "
+		    << dest->local () << ", "
+		    << dest->rank () << ")");
+	if (source->begin () < dest->begin ())
+	  if (dest->begin () < source->end ())
+	    if (dest->end () < source->end ())
+	      {
+		// NOTE: put into helper function to get overview
+		SpatialNegotiationData d (dest->begin (),
+					  dest->end (),
+					  dest->local () - source->local (),
+					  source->rank (),
+					  source->displ()+(dest->begin()-source->begin())
+					  );
+		buffers[dest->rank ()].push_back (d);
+		++dest;
+	      }
+	    else
+	      {
+		SpatialNegotiationData d (dest->begin (),
+					  source->end (),
+					  dest->local () - source->local (),
+					  source->rank (),
+					  source->displ()+(dest->begin()-source->begin())
+					  );
+		buffers[dest->rank ()].push_back (d);
+		++source;
+	      }
+	  else
+	    ++source;
+	else
+	  if (source->begin () < dest->end ())
+	    if (source->end () < dest->end ())
+	      {
+		SpatialNegotiationData d (source->begin (),
+					  source->end (),
+					  dest->local () - source->local (),
+					  source->rank (),
+					  source->displ()
+					  );
+		buffers[dest->rank ()].push_back (d);
+		++source;
+	      }
+	    else
+	      {
+		SpatialNegotiationData d (source->begin (),
+					  dest->end (),
+					  dest->local () - source->local (),
+					  source->rank (),
+					  source->displ()
+					  );
+		buffers[dest->rank ()].push_back (d);
+		++dest;
+	      }
+	  else
+	    ++dest;
+      }
+  }
+
+
+  void
+  SpatialNegotiator::send (MPI::Comm& comm,
+			   int destRank,
+			   NegotiationIntervals& intervals)
+  {
+    SpatialNegotiationData* data = &intervals[0];
+    int nIntervals = intervals.size ();
+    // first send size
+    comm.Send (&nIntervals, 1, MPI::INT, destRank, SPATIAL_NEGOTIATION_MSG);
+    comm.Send (data,
+	       sizeof (SpatialNegotiationData) / sizeof (int) * nIntervals,
+	       MPI::INT,
+	       destRank,
+	       SPATIAL_NEGOTIATION_MSG);
+  }
+
+
+  void
+  SpatialNegotiator::receive (MPI::Comm& comm,
+			      int sourceRank,
+			      NegotiationIntervals& intervals)
+  {
+    int nIntervals;
+    comm.Recv (&nIntervals, 1, MPI::INT, sourceRank, SPATIAL_NEGOTIATION_MSG);
+    intervals.resize (nIntervals);
+    comm.Recv (&intervals[0],
+	       sizeof (SpatialNegotiationData) / sizeof (int)
+	       * nIntervals,
+	       MPI::INT,
+	       sourceRank,
+	       SPATIAL_NEGOTIATION_MSG);
+  }
+
+
+  void
+  SpatialNegotiator::allToAll (std::vector<NegotiationIntervals>& out,
+			       std::vector<NegotiationIntervals>& in)
+  {
+    if (out.size () != nProcesses || in.size () != nProcesses)
+      error ("internal error in SpatialNegotiator::allToAll ()");
+    in[localRank] = out[localRank];
+    for (unsigned int i = 0; i < localRank; ++i)
+      receive (comm, i, in[i]);
+    for (unsigned int i = localRank + 1; i < nProcesses; ++i)
+      send (comm, i, out[i]);
+    for (unsigned int i = 0; i < localRank; ++i)
+      send (comm, i, out[i]);
+    for (unsigned int i = localRank + 1; i < nProcesses; ++i)
+      receive (comm, i, in[i]);
+  }
+  NegotiationIterator
+  SpatialNegotiator::negotiateSimple()
+  {
+      return wrapIntervals (indices->begin (),
+			    indices->end (),
+			    type,
+			    localRank);
+  }
+
+  SpatialOutputNegotiator::SpatialOutputNegotiator (IndexMap* indices,
+						    Index::Type type, MPI::Intracomm c,
+						    MPI::Intercomm ic)
+      : SpatialNegotiator (indices, type,  c)
+  {
+	     intercomm = ic;
+	    negotiateWidth ();
+  }
+
+
+  NegotiationIterator
+  SpatialOutputNegotiator::negotiate (int remoteNProc,
+		    Connector* connector)
+  {
+#ifdef MUSIC_DEBUG
+	  connector_ = connector;
+#endif
+	local.resize (nProcesses);
+	results.resize (nProcesses);
+	remote.resize (remoteNProc);
+    NegotiationIterator mappedDist = wrapIntervals (indices->begin (),
+						    indices->end (),
+						    type,
+						    localRank);
+    NegotiationIterator canonicalDist
+      = canonicalDistribution (width, nProcesses);
+
+    // NOTE: Find a better name for variable `results'
+    intersectToBuffers (mappedDist, canonicalDist, results);
+
+    // Send to virtual connector
+    allToAll (results, local);
+
+    // Receive from remote connector
+    for (int i = 0; i < remoteNProc; ++i)
+      receive (intercomm, i, remote[i]);
+    
+    results.resize (remoteNProc);
+    intersectToBuffers (local, remote, results);
+
+    // Send to remote connector
+    for (int i = 0; i < remoteNProc; ++i)
+      send (intercomm, i, results[i]);
+    
+    results.resize (nProcesses);
+    intersectToBuffers (remote, local, results);
+
+    // Send back to real connector
+    allToAll (results, local);
+
+    return NegotiationIterator (local);
+  }
+  
+  SpatialInputNegotiator::SpatialInputNegotiator (IndexMap* indices,
+						    Index::Type type, MPI::Intracomm c,
+						    MPI::Intercomm ic)
+      : SpatialNegotiator (indices, type,  c)
+  {
+	  intercomm = ic;
+	    negotiateWidth ();
+  }
+
+
+  NegotiationIterator
+  SpatialInputNegotiator::negotiate ( int remoteNProc,
+		    Connector* connector)
+  {
+#ifdef MUSIC_DEBUG
+	  connector_ = connector;
+#endif
+    remote.resize (remoteNProc);
+    NegotiationIterator mappedDist = wrapIntervals (indices->begin (),
+						    indices->end (),
+						    type,
+						    localRank);
+    NegotiationIterator canonicalDist
+      = canonicalDistribution (width, remoteNProc);
+    intersectToBuffers (mappedDist, canonicalDist, remote);
+    for (int i = 0; i < remoteNProc; ++i)
+      send (intercomm, i, remote[i]);
+    for (int i = 0; i < remoteNProc; ++i)
+      receive (intercomm, i, remote[i]);
+    
+    return NegotiationIterator (remote);
+  }
+
+}
+#endif
diff --git a/src/subconnector.cc b/src/subconnector.cc
new file mode 100644
index 0000000..19cf54c
--- /dev/null
+++ b/src/subconnector.cc
@@ -0,0 +1,888 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009, 2010 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/subconnector.hh"
+
+#include "music/debug.hh"
+
+#if MUSIC_USE_MPI
+
+#include "music/communication.hh"
+#include "music/event_router.hh"
+
+#include <cstring>
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#ifdef MUSIC_DEBUG
+#include <cstdlib>
+#endif
+
+namespace MUSIC {
+
+Subconnector::Subconnector (MPI::Datatype type,
+		MPI::Intercomm intercomm_,
+		int remoteLeader,
+		int remoteRank,
+		int receiverRank,
+		int receiverPortCode)
+: type_ (type),
+		intercomm (intercomm_),
+		remoteRank_ (remoteRank),
+		remoteWorldRank_ (remoteLeader + remoteRank),
+		receiverRank_ (receiverRank),
+		receiverPortCode_ (receiverPortCode),
+		flushed(false)
+{
+}
+
+
+Subconnector::~Subconnector ()
+{
+}
+
+
+BufferingOutputSubconnector::BufferingOutputSubconnector (int elementSize)
+: buffer_ (elementSize)
+{
+}
+
+
+
+
+
+/********************************************************************
+ *
+ * Cont Subconnectors
+ *
+ ********************************************************************/
+
+ContOutputSubconnector::ContOutputSubconnector (//Synchronizer* synch_,
+		MPI::Intercomm intercomm_,
+		int remoteLeader,
+		int remoteRank,
+		int receiverPortCode_,
+		MPI::Datatype type)
+: Subconnector (type,
+		intercomm_,
+		remoteLeader,
+		remoteRank,
+		remoteRank,
+		receiverPortCode_),
+		BufferingOutputSubconnector (0)
+{
+}
+
+
+void
+ContOutputSubconnector::initialCommunication (double param)
+{
+	send ();
+}
+
+
+void
+ContOutputSubconnector::maybeCommunicate ()
+{
+	if(!flushed)
+		send ();
+}
+
+
+void
+ContOutputSubconnector::send ()
+{
+
+	void* data;
+	int size;
+	buffer_.nextBlock (data, size);
+	// NOTE: marshalling
+	char* buffer = static_cast <char*> (data);
+
+	while (size >= CONT_BUFFER_MAX)
+	{
+
+		MUSIC_LOGR ("Sending to rank " << remoteRank_);
+		intercomm.Ssend (buffer,
+				CONT_BUFFER_MAX / type_.Get_size (),
+				type_,
+				remoteRank_,
+				CONT_MSG);
+		buffer += CONT_BUFFER_MAX;
+		size -= CONT_BUFFER_MAX;
+	}
+	MUSIC_LOGR ("Last send to rank " << remoteRank_);
+	intercomm.Ssend (buffer,
+			size / type_.Get_size (),
+			type_,
+			remoteRank_,
+			CONT_MSG);
+}
+
+
+void
+ContOutputSubconnector::flush (bool& dataStillFlowing)
+{
+	if (!flushed)
+	{
+		if (!buffer_.isEmpty ())
+		{
+			MUSIC_LOGR ("sending data remaining in buffers");
+			send ();
+			dataStillFlowing = true;
+		}
+		else
+		{
+			char dummy;
+			intercomm.Ssend (&dummy, 0, type_, remoteRank_, FLUSH_MSG);
+			flushed = true;
+		}
+	}
+}
+
+
+ContInputSubconnector::ContInputSubconnector (//Synchronizer* synch_,
+		MPI::Intercomm intercomm,
+		int remoteLeader,
+		int remoteRank,
+		int receiverRank,
+		int receiverPortCode,
+		MPI::Datatype type)
+: Subconnector (type,
+		intercomm,
+		remoteLeader,
+		remoteRank,
+		receiverRank,
+		receiverPortCode),
+		InputSubconnector ()
+{
+}
+
+
+void
+ContInputSubconnector::initialCommunication (double initialBufferedTicks)
+{
+	receive ();
+
+	buffer_.fill (initialBufferedTicks);
+}
+
+
+void
+ContInputSubconnector::maybeCommunicate ()
+{
+	if (!flushed)
+		receive ();
+}
+
+
+void
+ContInputSubconnector::receive ()
+{
+	char* data;
+	MPI::Status status;
+	int size, maxCount;
+	maxCount = CONT_BUFFER_MAX / type_.Get_size ();
+	do
+	{
+		data = static_cast<char*> (buffer_.insertBlock ());
+		MUSIC_LOGR ("Receiving from rank " << remoteRank_);
+
+		intercomm.Recv (data,
+				maxCount,
+				type_,
+				remoteRank_,
+				MPI::ANY_TAG,
+				status);
+		if (status.Get_tag () == FLUSH_MSG)
+		{
+			flushed = true;
+			MUSIC_LOGR ("received flush message");
+			return;
+		}
+		size = status.Get_count (type_);
+		buffer_.trimBlock (type_.Get_size () * size);
+	}
+	while (size == maxCount);
+}
+
+
+void
+ContInputSubconnector::flush (bool& dataStillFlowing)
+{
+	if (!flushed)
+	{
+		//MUSIC_LOGR ("receiving and throwing away data");
+		receive ();
+		if (!flushed)
+			dataStillFlowing = true;
+	}
+}
+
+/********************************************************************
+ *
+ * Event Subconnectors
+ *
+ ********************************************************************/
+
+
+EventOutputSubconnector::EventOutputSubconnector (//Synchronizer* synch_,
+		MPI::Intercomm intercomm,
+		int remoteLeader,
+		int remoteRank,
+		int receiverPortCode)
+: Subconnector (MPI::BYTE,
+		intercomm,
+		remoteLeader,
+		remoteRank,
+		remoteRank,
+		receiverPortCode),
+		BufferingOutputSubconnector (sizeof (Event))
+{
+}
+
+void
+EventOutputSubconnector::maybeCommunicate ()
+{
+	send ();
+
+}
+void
+EventOutputSubconnector::maybeCommunicate (std::vector<MPI::Request> &requests)
+{
+	send (requests);
+}
+
+void
+EventOutputSubconnector::send (std::vector<MPI::Request> &requests)
+{
+	MUSIC_LOGRE ("ISend");
+	void* data;
+	int size;
+	buffer_.nextBlock (data, size);
+	char* buffer = static_cast <char*> (data);
+	while (size >= SPIKE_BUFFER_MAX)
+	{
+		requests.push_back(intercomm.Isend (buffer,
+				SPIKE_BUFFER_MAX,
+				type_,
+				remoteRank_,
+				SPIKE_MSG));
+		buffer += SPIKE_BUFFER_MAX;
+		size -= SPIKE_BUFFER_MAX;
+	}
+	requests.push_back( intercomm.Isend (buffer, size, type_, remoteRank_, SPIKE_MSG));
+}
+void
+EventOutputSubconnector::send ()
+{
+	MUSIC_LOGRE ("Ssend");
+	void* data;
+	int size;
+	buffer_.nextBlock (data, size);
+	char* buffer = static_cast <char*> (data);
+	while (size >= SPIKE_BUFFER_MAX)
+	{
+		intercomm.Ssend (buffer,
+				SPIKE_BUFFER_MAX,
+				type_,
+				remoteRank_,
+				SPIKE_MSG);
+		buffer += SPIKE_BUFFER_MAX;
+		size -= SPIKE_BUFFER_MAX;
+	}
+	intercomm.Ssend (buffer, size, type_, remoteRank_, SPIKE_MSG);
+}
+
+void
+EventOutputSubconnector::flush (bool& dataStillFlowing)
+{
+	if (!flushed)
+	{
+		if (!buffer_.isEmpty ())
+		{
+			MUSIC_LOGR ("sending data remaining in buffers");
+			send ();
+			dataStillFlowing = true;
+		}
+		/* remedius
+		 * flushed flag was added since synchronous communication demands equal sends and receives
+		 */
+		else
+		{
+			Event* e = static_cast<Event*> (buffer_.insert ());
+			e->id = FLUSH_MARK;
+			send ();
+			flushed = true;
+		}
+	}
+}
+
+
+EventInputSubconnector::EventInputSubconnector (//Synchronizer* synch_,
+		MPI::Intercomm intercomm,
+		int remoteLeader,
+		int remoteRank,
+		int receiverRank,
+		int receiverPortCode)
+: Subconnector (MPI::BYTE,
+		intercomm,
+		remoteLeader,
+		remoteRank,
+		receiverRank,
+		receiverPortCode),
+		InputSubconnector ()
+{
+}
+
+
+EventInputSubconnectorGlobal::EventInputSubconnectorGlobal
+(//Synchronizer* synch_,
+		MPI::Intercomm intercomm,
+		int remoteLeader,
+		int remoteRank,
+		int receiverRank,
+		int receiverPortCode,
+		EventHandlerGlobalIndex* eh)
+: Subconnector (MPI::BYTE,
+		intercomm,
+		remoteLeader,
+		remoteRank,
+		receiverRank,
+		receiverPortCode),
+		EventInputSubconnector (//synch_,
+				intercomm,
+				remoteLeader,
+				remoteRank,
+				receiverRank,
+				receiverPortCode),
+				handleEvent (eh)
+{
+
+
+}
+
+
+//EventHandlerGlobalIndexDummy
+//EventInputSubconnectorGlobal::dummyHandler;
+
+
+EventInputSubconnectorLocal::EventInputSubconnectorLocal
+(//Synchronizer* synch_,
+		MPI::Intercomm intercomm,
+		int remoteLeader,
+		int remoteRank,
+		int receiverRank,
+		int receiverPortCode,
+		EventHandlerLocalIndex* eh)
+: Subconnector (MPI::BYTE,
+		intercomm,
+		remoteLeader,
+		remoteRank,
+		receiverRank,
+		receiverPortCode),
+		EventInputSubconnector (
+				intercomm,
+				remoteLeader,
+				remoteRank,
+				receiverRank,
+				receiverPortCode),
+				handleEvent (eh)
+{
+}
+
+
+//EventHandlerLocalIndexDummy
+//EventInputSubconnectorLocal::dummyHandler;
+
+
+void
+EventInputSubconnector::maybeCommunicate ()
+{
+	if (!flushed )
+		receive ();
+}
+
+bool
+EventInputSubconnectorGlobal::receive (char *data, int size)
+{
+		Event* ev = (Event*) data;
+		/* remedius
+		 * since the message can be of size 0 and contains garbage=FLUSH_MARK,
+		 * the check for the size of the message was added.
+		 */
+		if (ev[0].id == FLUSH_MARK  && size > 0)
+		{
+			flushed = true;
+			MUSIC_LOGR ("received flush message");
+		}
+		else
+		{
+			int nEvents = size / sizeof (Event);
+			for (int i = 0; i < nEvents; ++i){
+				(*handleEvent) (ev[i].t, ev[i].id);
+			}
+		}
+		return flushed;
+}
+// NOTE: isolate difference between global and local to avoid code repetition
+void
+EventInputSubconnectorGlobal::receive ()
+{
+	char data[SPIKE_BUFFER_MAX];
+	MPI::Status status;
+	int size;
+	//double starttime, endtime;
+	//starttime = MPI_Wtime();
+
+	do
+	{
+		intercomm.Recv (data,
+				SPIKE_BUFFER_MAX,
+				type_,
+				remoteRank_,
+				SPIKE_MSG,
+				status);
+
+		size = status.Get_count (type_);
+		Event* ev = (Event*) data;
+		/* remedius
+		 * since the message can be of size 0 and contains garbage=FLUSH_MARK,
+		 * the check for the size of the message was added.
+		 */
+		if (ev[0].id == FLUSH_MARK  && size > 0)
+		{
+			flushed = true;
+			MUSIC_LOGR ("received flush message");
+			return;
+		}
+
+
+		int nEvents = size / sizeof (Event);
+
+		for (int i = 0; i < nEvents; ++i){
+			(*handleEvent) (ev[i].t, ev[i].id);
+		}
+
+	}
+	while (size == SPIKE_BUFFER_MAX);
+	//endtime = MPI_Wtime();
+	//endtime = endtime-starttime;
+	//if(tt < endtime)
+	//tt = endtime;
+
+}
+
+
+void
+EventInputSubconnectorLocal::receive ()
+{
+	MUSIC_LOGRE ("receive");
+	char data[SPIKE_BUFFER_MAX];
+	MPI::Status status;
+	int size;
+	do
+	{
+		intercomm.Recv (data,
+				SPIKE_BUFFER_MAX,
+				type_,
+				remoteRank_,
+				SPIKE_MSG,
+				status);
+		size = status.Get_count (type_);
+		Event* ev = (Event*) data;
+		/* remedius
+		 * since the message can be of size 0 and contains garbage=FLUSH_MARK,
+		 * the check for the size of the message was added.
+		 */
+		if (ev[0].id == FLUSH_MARK && size > 0)
+		{
+			flushed = true;
+			return;
+		}
+		int nEvents = size / sizeof (Event);
+		for (int i = 0; i < nEvents; ++i)
+			(*handleEvent) (ev[i].t, ev[i].id);
+	}
+	while (size == SPIKE_BUFFER_MAX);
+}
+
+
+void
+EventInputSubconnector::flush (bool& dataStillFlowing)
+{
+	if (!flushed)
+	{
+		//MUSIC_LOGRE ("receiving and throwing away data");
+		receive ();
+		if (!flushed)
+			dataStillFlowing = true;
+	}
+}
+
+
+/*void
+EventInputSubconnectorGlobal::flush (bool& dataStillFlowing)
+{
+	//handleEvent = &dummyHandler;
+	EventInputSubconnector::flush (dataStillFlowing);
+}
+
+
+void
+EventInputSubconnectorLocal::flush (bool& dataStillFlowing)
+{
+	//handleEvent = &dummyHandler;
+	EventInputSubconnector::flush (dataStillFlowing);
+}*/
+
+/********************************************************************
+ *
+ * Message Subconnectors
+ *
+ ********************************************************************/
+
+MessageOutputSubconnector::MessageOutputSubconnector (//Synchronizer* synch_,
+		MPI::Intercomm intercomm,
+		int remoteLeader,
+		int remoteRank,
+		int receiverPortCode,
+		FIBO* buffer)
+: Subconnector (MPI::BYTE,
+		intercomm,
+		remoteLeader,
+		remoteRank,
+		remoteRank,
+		receiverPortCode),
+		buffer_ (buffer)
+{
+}
+
+
+void
+MessageOutputSubconnector::maybeCommunicate ()
+{
+	if (!flushed)
+		send ();
+}
+
+
+void
+MessageOutputSubconnector::send ()
+{
+	void* data;
+	int size;
+	buffer_->nextBlockNoClear (data, size);
+	// NOTE: marshalling
+	char* buffer = static_cast <char*> (data);
+	while (size >= MESSAGE_BUFFER_MAX)
+	{
+		intercomm.Ssend (buffer,
+				MESSAGE_BUFFER_MAX,
+				type_,
+				remoteRank_,
+				MESSAGE_MSG);
+		buffer += MESSAGE_BUFFER_MAX;
+		size -= MESSAGE_BUFFER_MAX;
+	}
+	intercomm.Ssend (buffer, size, type_, remoteRank_, MESSAGE_MSG);
+}
+
+
+void
+MessageOutputSubconnector::flush (bool& dataStillFlowing)
+{
+	if (!flushed)
+	{
+		if (!buffer_->isEmpty ())
+		{
+			MUSIC_LOGRE ("sending data remaining in buffers");
+			send ();
+			dataStillFlowing = true;
+		}
+		else
+		{
+			char dummy;
+			intercomm.Ssend (&dummy, 0, type_, remoteRank_, FLUSH_MSG);
+		}
+	}
+}
+
+
+MessageInputSubconnector::MessageInputSubconnector (//Synchronizer* synch_,
+		MPI::Intercomm intercomm,
+		int remoteLeader,
+		int remoteRank,
+		int receiverRank,
+		int receiverPortCode,
+		MessageHandler* mh)
+: Subconnector (MPI::BYTE,
+		intercomm,
+		remoteLeader,
+		remoteRank,
+		receiverRank,
+		receiverPortCode),
+		handleMessage (mh)
+{
+}
+
+
+//MessageHandlerDummy
+//MessageInputSubconnector::dummyHandler;
+
+
+void
+MessageInputSubconnector::maybeCommunicate ()
+{
+	if (!flushed)// && synch->communicate ())
+		receive ();
+}
+
+
+void
+MessageInputSubconnector::receive ()
+{
+	char data[MESSAGE_BUFFER_MAX];
+	MPI::Status status;
+	int size;
+	do
+	{
+		intercomm.Recv (data,
+				MESSAGE_BUFFER_MAX,
+				type_,
+				remoteRank_,
+				MPI::ANY_TAG,
+				status);
+		if (status.Get_tag () == FLUSH_MSG)
+		{
+			flushed = true;
+			MUSIC_LOGRE ("received flush message");
+			return;
+		}
+		size = status.Get_count (type_);
+		int current = 0;
+		while (current < size)
+		{
+			MessageHeader* header = static_cast<MessageHeader*>
+			(static_cast<void*> (&data[current]));
+			current += sizeof (MessageHeader);
+			(*handleMessage) (header->t (), &data[current], header->size ());
+			current += header->size ();
+		}
+	}
+	while (size == MESSAGE_BUFFER_MAX);
+}
+
+
+void
+MessageInputSubconnector::flush (bool& dataStillFlowing)
+{
+	//handleMessage = &dummyHandler;
+	if (!flushed)
+	{
+		//MUSIC_LOGRE ("receiving and throwing away data");
+		receive ();
+		if (!flushed)
+			dataStillFlowing = true;
+	}
+}
+
+/********************************************************************
+ *
+ * Collective Subconnector
+ *
+ ********************************************************************/
+
+CollectiveSubconnector::CollectiveSubconnector (MPI::Intracomm intracomm)
+  : intracomm_ (intracomm)
+{
+}
+
+
+CollectiveSubconnector::~CollectiveSubconnector ()
+{
+}
+
+void
+CollectiveSubconnector::allocAllgathervArrays ()
+{
+  nProcesses = intracomm_.Get_size ();
+  ppBytes = new int[nProcesses];
+  displ = new int[nProcesses];
+}
+
+void
+CollectiveSubconnector::freeAllgathervArrays ()
+{
+  delete ppBytes;
+  delete displ;  
+}
+
+void
+CollectiveSubconnector::maybeCommunicate ()
+{
+  if (!flushed)
+    communicate ();
+}
+
+int
+CollectiveSubconnector::calcCommDataSize (int local_data_size)
+{
+  int dsize;
+  //distributing the size of the buffer
+  intracomm_.Allgather (&local_data_size, 1, MPI_INT, ppBytes, 1, MPI_INT);
+  //could it be that dsize is more then unsigned int?
+  dsize = 0;
+  for(int i=0; i < nProcesses; ++i){
+    displ[i] = dsize;
+    dsize += ppBytes[i];
+    //ppBytes[i] /= type_.Get_size();
+    /*		  if(ppBytes[i] > max_size)
+		  max_size = ppBytes[i];*/
+  }
+  return dsize;
+}
+
+/* remedius
+ * current collective communication is realized through two times calls of
+ * mpi allgather function: first time the size of the data is distributed,
+ * the second time the data by itself is distributed.
+ * Probably that could be not optimal for a huge # of ranks.
+ */
+std::vector<char> CollectiveSubconnector::getCommData(char *cur_buff, int size)
+{
+  unsigned int dsize;
+  char *recv_buff;
+  std::vector<char> commData;
+  recv_buff=NULL;
+
+  dsize = calcCommDataSize(size);
+
+  if(dsize > 0){
+    //distributing the data
+    recv_buff = new char[dsize];
+    intracomm_.Allgatherv(cur_buff, size, MPI::BYTE, recv_buff, ppBytes, displ, MPI::BYTE );
+    std::copy(recv_buff,recv_buff+dsize,std::back_inserter(commData));
+    delete[] recv_buff;
+  }
+  return commData;
+}
+
+
+void
+EventOutputCollectiveSubconnector::setOutputBuffer (void* buffer,
+						    unsigned int size)
+{
+  router_->setOutputBuffer (buffer, size);
+}
+
+
+unsigned int
+EventOutputCollectiveSubconnector::dataSize ()
+{
+  return router_->dataSize ();
+}
+
+
+void
+EventOutputCollectiveSubconnector::fillOutputBuffer ()
+{
+  router_->fillOutputBuffer ();
+}
+
+
+void
+EventInputCollectiveSubconnector::processData (void* data, unsigned int size)
+{
+  Event* e = static_cast<Event*> (data);
+  while (size > 0)
+    {
+      router_->processEvent (e->t, e->id);
+      ++e;
+      size -= sizeof (Event);
+    }
+}
+
+
+void
+ContCollectiveSubconnector::maybeCommunicate(){
+	CollectiveSubconnector::maybeCommunicate();
+}
+void ContCollectiveSubconnector::communicate(){
+	int size, bSize, nBuffered;
+	void *data;
+	char *cur_buff, *dest_buff;
+	std::vector<char> commData;
+	if(flushed)
+		return;
+	ContOutputSubconnector::buffer_.nextBlock (data, size);
+	commData = getCommData(static_cast <char*> (data), size);
+	const int* displ = getDisplArr();
+	//std::copy(commData.begin(),commData.end(),cur_buff);
+	cur_buff = (char*)static_cast<void*> (&commData[0]);
+	flushed = commData.size() == 0 ? true : false;
+	nBuffered= commData.size() / width_; //the received data size is always multiple of port width
+	for(int i =0; i < nBuffered ; ++i){
+		bSize = 0;
+		dest_buff = static_cast<char*> (ContInputSubconnector::buffer_.insertBlock ());
+		for (std::multimap<int, Interval>::iterator it=
+				intervals_.begin() ; it != intervals_.end(); it++ ) //iterates all the intervals
+		{
+			memcpy (dest_buff + bSize,
+					cur_buff
+					+displ[(*it).first]//+displacement of data for a current rank
+					+i*blockSizePerRank_[(*it).first]  //+displacement of the appropriate buffered chunk of data within current rank data block
+					+(*it).second.begin(), //+displacement of the requested data
+					(*it).second.end()); // length field is stored overlapping the end field
+			bSize += (*it).second.end();
+		}
+		ContInputSubconnector::buffer_.trimBlock (bSize);
+	}
+}
+void ContCollectiveSubconnector::initialCommunication(double initialBufferedTicks){
+	communicate();
+	fillBlockSizes();
+	ContInputSubconnector::buffer_.fill (initialBufferedTicks);
+}
+void ContCollectiveSubconnector::fillBlockSizes()
+{
+	std::map<int, Interval>::iterator it;
+	const int* ppBytes = getSizeArr();
+	for ( it=intervals_.begin() ; it != intervals_.end(); it++ ) //iterates all the intervals
+		blockSizePerRank_[(*it).first]= ppBytes[(*it).first];
+}
+void ContCollectiveSubconnector::flush(bool& dataStillFlowing){
+	if (!flushed)
+	{
+		if (!ContOutputSubconnector::buffer_.isEmpty ())
+		{
+			MUSIC_LOGR ("sending data remaining in buffers");
+			maybeCommunicate ();
+			dataStillFlowing = true;
+		}
+		else
+		{
+			//a sign for the end of communication will be an empty buffer
+			communicate ();
+			if(!flushed)
+				dataStillFlowing = true;
+		}
+	}
+}
+}
+#endif
diff --git a/src/temporal.cc b/src/temporal.cc
new file mode 100644
index 0000000..51f9fe5
--- /dev/null
+++ b/src/temporal.cc
@@ -0,0 +1,502 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/temporal.hh"  // Must be included first on BG/L
+//#define MUSIC_DEBUG
+
+#if MUSIC_USE_MPI
+
+#include "music/setup.hh"
+
+namespace MUSIC
+{
+
+  TemporalNegotiator::TemporalNegotiator (Setup* setup) :
+      setup_ (setup), negotiationBuffer (NULL)
+  {
+    nApplications_ = setup_->applicationMap ()->size ();
+    nAllConnections = 0;
+    nodes = new TemporalNegotiatorGraph (setup_->timebase (), nApplications_,
+        setup_->applicationColor ());
+  }
+
+
+  TemporalNegotiator::~TemporalNegotiator ()
+  {
+    delete nodes;
+    freeNegotiationData (negotiationBuffer);
+
+    // Free negotiation communicator in application leaders
+    if (negotiationComm != MPI::COMM_NULL)
+      negotiationComm.Free ();
+
+    applicationLeaders.Free ();
+    groupWorld.Free ();
+  }
+
+
+  void
+  TemporalNegotiator::separateConnections (
+      std::vector<Connection*>* connections)
+  {
+    for (std::vector<Connection*>::iterator c = connections->begin ();
+        c != connections->end (); ++c)
+      {
+        if (dynamic_cast<OutputConnection*> (*c) != NULL)
+          outputConnections.push_back (*dynamic_cast<OutputConnection*> (*c));
+        else
+          inputConnections.push_back (*dynamic_cast<InputConnection*> (*c));
+      }
+  }
+
+
+  TemporalNegotiatorGraph*
+  TemporalNegotiator::applicationGraph ()
+  {
+    return nodes;
+  }
+
+
+  bool
+  TemporalNegotiator::isLeader ()
+  {
+    return setup_->communicator ().Get_rank () == 0;
+  }
+
+
+  bool
+  TemporalNegotiator::hasPeers ()
+  {
+    return setup_->communicator ().Get_size () > 1;
+  }
+
+
+  void
+  TemporalNegotiator::createNegotiationCommunicator ()
+  {
+    ApplicationMap* applicationMap = setup_->applicationMap ();
+    int* ranks = new int[nApplications_];
+
+    for (int i = 0; i < nApplications_; ++i)
+      ranks[i] = (*applicationMap)[i].leader ();
+
+    groupWorld = MPI::COMM_WORLD.Get_group ();
+    applicationLeaders = groupWorld.Incl (nApplications_, ranks);
+    delete[] ranks;
+    negotiationComm = MPI::COMM_WORLD.Create (applicationLeaders);
+  }
+
+
+  int
+  TemporalNegotiator::negotiationDataSize (int nConnections)
+  {
+    return negotiationDataSize (1, nConnections);
+  }
+
+
+  int
+  TemporalNegotiator::negotiationDataSize (int nBlocks, int nConnections)
+  {
+    // -1 due to definition of connection member
+    return (nBlocks * sizeof(TemporalNegotiationData)
+        + (nConnections - 1) * sizeof(ConnectionDescriptor));
+  }
+
+
+  TemporalNegotiationData*
+  TemporalNegotiator::allocNegotiationData (int nBlocks, int nConnections)
+  {
+    void* memory = new char[negotiationDataSize (nBlocks, nConnections)];
+    return static_cast<TemporalNegotiationData*> (memory);
+  }
+
+
+  void
+  TemporalNegotiator::freeNegotiationData (TemporalNegotiationData* data)
+  {
+    if (data != NULL)
+      {
+        delete[] static_cast<char*> (static_cast<void*> (data));
+        data = NULL;
+      }
+  }
+
+
+  int
+  TemporalNegotiator::computeDefaultMaxBuffered (int maxLocalWidth,
+      int eventSize, ClockState tickInterval, double timebase)
+  {
+    int res;
+
+    // Do different calculation depending on the kind of port
+
+    // NOTE: We should not base this choice eventSize but instead on
+    // proper type information
+
+    if (eventSize == 0)
+      // continuous data
+      res = DEFAULT_PACKET_SIZE / maxLocalWidth;
+    else if (eventSize == 1)
+      // message data
+      res = DEFAULT_MESSAGE_MAX_BUFFERED;
+    else
+      // event data
+      res = (DEFAULT_PACKET_SIZE
+          / (EVENT_FREQUENCY_ESTIMATE * maxLocalWidth * eventSize * timebase
+              * tickInterval));
+    if (res < 1)
+      res = 1;
+    return res;
+  }
+
+
+  int
+  TemporalNegotiator::findNodeColor (int leader)
+  {
+    int color = -1;
+    ApplicationMap* applicationMap = setup_->applicationMap ();
+    for (int i = 0; i < nApplications_; ++i)
+      if (leader == (*applicationMap)[i].leader ())
+        color = (*applicationMap)[i].color ();
+    assert (color != -1);
+    return color;
+  }
+
+
+  void
+  TemporalNegotiator::collectNegotiationData (ClockState ti)
+  {
+    int nOut = outputConnections.size ();
+    int nIn = inputConnections.size ();
+    nLocalConnections = nOut + nIn;
+    MUSIC_LOG ("nLocalConnections = " << nLocalConnections
+        << ", nOut = " << nOut
+        << ", nIn = " << nIn);
+    negotiationData = allocNegotiationData (1, nLocalConnections);
+    negotiationData->timebase = setup_->timebase ();
+    negotiationData->tickInterval = ti;
+    negotiationData->color = setup_->applicationColor ();
+    negotiationData->leader = setup_->leader ();
+    negotiationData->nProcs = setup_->nProcs ();
+    negotiationData->nOutConnections = outputConnections.size ();
+    negotiationData->nInConnections = inputConnections.size ();
+
+    for (int i = 0; i < nOut; ++i)
+      {
+        Connector* connector = outputConnections[i].connector ();
+        int remote = connector->remoteLeader ();
+        negotiationData->connection[i].remoteNode = findNodeColor (remote);
+        negotiationData->connection[i].receiverPort =
+            connector->receiverPortCode ();
+        negotiationData->connection[i].multiComm = connector->idFlag ();
+        negotiationData->connection[i].maxBuffered =
+            outputConnections[i].maxBuffered ();
+        negotiationData->connection[i].defaultMaxBuffered =
+            computeDefaultMaxBuffered (connector->maxLocalWidth (),
+                outputConnections[i].elementSize (), ti, setup_->timebase ());
+
+        negotiationData->connection[i].accLatency = 0;
+      }
+    for (int i = 0; i < nIn; ++i)
+      {
+        int remote = inputConnections[i].connector ()->remoteLeader ();
+        negotiationData->connection[nOut + i].remoteNode = findNodeColor (
+            remote);
+        negotiationData->connection[nOut + i].receiverPort =
+            inputConnections[i].connector ()->receiverPortCode ();
+        negotiationData->connection[nOut + i].multiComm =
+            inputConnections[i].connector ()->idFlag ();
+        negotiationData->connection[nOut + i].maxBuffered =
+            inputConnections[i].maxBuffered ();
+        negotiationData->connection[nOut + i].defaultMaxBuffered = 0;
+
+        negotiationData->connection[nOut + i].accLatency =
+            inputConnections[i].accLatency ();
+        MUSIC_LOGR ("port " << inputConnections[i].connector ()->receiverPortName () << ": " << inputConnections[i].accLatency ());
+        negotiationData->connection[nOut + i].interpolate =
+            inputConnections[i].interpolate ();
+      }
+  }
+
+
+  void
+  TemporalNegotiator::fillTemporalNegotiatorGraph ()
+  {
+    nodes->setNConnections (nAllConnections / 2);
+    char* memory = static_cast<char*> (static_cast<void*> (negotiationBuffer));
+    TemporalNegotiationData* data;
+    for (int i = 0; i < nApplications_; ++i)
+      {
+
+        data =
+            static_cast<TemporalNegotiationData*> (static_cast<void*> (memory));
+        int nOut = data->nOutConnections;
+        int nIn = data->nInConnections;
+        nodes->addNode (
+            ANode<TemporalNegotiationData, ConnectionDescriptor> (nOut, nIn,
+                *data), data->color);
+        memory += negotiationDataSize (nOut + nIn);
+      }
+
+  }
+
+
+  void
+  TemporalNegotiator::communicateNegotiationData ()
+  {
+    // First talk to others about how many connections each node has
+    int* nConnections = new int[nApplications_];
+    negotiationComm.Allgather (&nLocalConnections, 1, MPI::INT, nConnections, 1,
+        MPI::INT);
+    for (int i = 0; i < nApplications_; ++i)
+      nAllConnections += nConnections[i];
+    negotiationBuffer = allocNegotiationData (nApplications_, nAllConnections);
+    int* receiveSizes = new int[nApplications_];
+    int* displacements = new int[nApplications_];
+    int displacement = 0;
+    for (int i = 0; i < nApplications_; ++i)
+      {
+        int receiveSize = negotiationDataSize (nConnections[i]);
+        receiveSizes[i] = receiveSize;
+        displacements[i] = displacement;
+
+        displacement += receiveSize;
+      }
+    delete[] nConnections;
+    int sendSize = negotiationDataSize (nLocalConnections);
+    negotiationComm.Allgatherv (negotiationData, sendSize, MPI::BYTE,
+        negotiationBuffer, receiveSizes, displacements, MPI::BYTE);
+    delete[] displacements;
+    delete[] receiveSizes;
+    freeNegotiationData (negotiationData);
+    fillTemporalNegotiatorGraph ();
+  }
+
+
+  ConnectionDescriptor*
+  TemporalNegotiator::findInputConnection (int node, int port)
+  {
+    int nOut = nodes->at (node).data ().nOutConnections;
+    // Get address of first input ConnectionDescriptor
+    ConnectionDescriptor* inputDescriptors =
+        &nodes->at (node).data ().connection[nOut];
+    for (int i = 0; i < nodes->at (node).data ().nInConnections; ++i)
+      if (inputDescriptors[i].receiverPort == port)
+        return &inputDescriptors[i];
+    error ("internal error in TemporalNegotiator::findInputConnection");
+    return 0; // never reached
+  }
+
+
+  void
+  TemporalNegotiator::combineParameters ()
+  {
+    double timebase = nodes->at (0).data ().timebase;
+
+    for (int o = 0; o < nApplications_; ++o)
+      {
+        // check timebase
+        if (nodes->at (o).data ().timebase != timebase)
+          error0 ("applications don't use same timebase");
+
+        for (int c = 0; c < nodes->at (o).data ().nOutConnections; ++c)
+          {
+            ConnectionDescriptor* out = &nodes->at (o).data ().connection[c];
+            int i = out->remoteNode;
+            ConnectionDescriptor* in = findInputConnection (i,
+                out->receiverPort);
+
+            // maxBuffered
+
+            // check defaults
+            if (out->maxBuffered == MAX_BUFFERED_NO_VALUE
+                && in->maxBuffered == MAX_BUFFERED_NO_VALUE)
+              out->maxBuffered = out->defaultMaxBuffered;
+            else if (in->maxBuffered != MAX_BUFFERED_NO_VALUE)
+              {
+                // convert to sender side ticks
+                ClockState inMaxBufferedTime = in->maxBuffered
+                    * nodes->at (i).data ().tickInterval;
+                int inMaxBuffered = (inMaxBufferedTime
+                    / nodes->at (o).data ().tickInterval);
+                // take min maxBuffered
+                if (out->maxBuffered == MAX_BUFFERED_NO_VALUE
+                    || inMaxBuffered < out->maxBuffered)
+                  out->maxBuffered = inMaxBuffered;
+              }
+            // store maxBuffered in sender units
+            in->maxBuffered = out->maxBuffered;
+            MUSIC_LOG0("Max Buffered:"<<in->maxBuffered);
+
+            // accLatency
+            out->accLatency = in->accLatency;
+
+            // interpolate
+            out->interpolate = in->interpolate;
+
+            // remoteTickInterval
+            out->remoteTickInterval = nodes->at (i).data ().tickInterval;
+            in->remoteTickInterval = nodes->at (o).data ().tickInterval;
+          }
+      }
+  }
+
+
+  void
+  TemporalNegotiator::distributeParameters ()
+  {
+    for (int o = 0; o < nApplications_; ++o)
+      {
+        for (int c = 0; c < nodes->at (o).data ().nOutConnections; ++c)
+          {
+            ConnectionDescriptor* out = &nodes->at (o).data ().connection[c];
+            int i = out->remoteNode;
+            ConnectionDescriptor* in = findInputConnection (i,
+                out->receiverPort);
+
+            // store maxBuffered in sender units
+            in->maxBuffered = out->maxBuffered;
+          }
+      }
+  }
+
+
+  void
+  TemporalNegotiator::loopAlgorithm ()
+  {
+    std::vector<AEdge<TemporalNegotiationData, ConnectionDescriptor> > path;
+    TemporalNegotiatorGraph::iterator it;
+    for (it = nodes->begin (); it < nodes->end (); ++it)
+      if (!it->visited)
+        nodes->depthFirst (*it, path);
+  }
+
+
+  void
+  TemporalNegotiator::broadcastNegotiationData ()
+  {
+    MPI::Intracomm comm = setup_->communicator ();
+
+    if (hasPeers ())
+      {
+        comm.Bcast (&nAllConnections, 1, MPI::INT, 0);
+        char* memory =
+            static_cast<char*> (static_cast<void*> (negotiationBuffer));
+        comm.Bcast (memory,
+            negotiationDataSize (nApplications_, nAllConnections), MPI::BYTE,
+            0);
+      }
+  }
+
+
+  void
+  TemporalNegotiator::receiveNegotiationData ()
+  {
+    MPI::Intracomm comm = setup_->communicator ();
+    comm.Bcast (&nAllConnections, 1, MPI::INT, 0);
+    negotiationBuffer = allocNegotiationData (nApplications_, nAllConnections);
+    char* memory = static_cast<char*> (static_cast<void*> (negotiationBuffer));
+    comm.Bcast (memory, negotiationDataSize (nApplications_, nAllConnections),
+        MPI::BYTE, 0);
+    fillTemporalNegotiatorGraph ();
+  }
+
+
+  void
+  TemporalNegotiator::negotiate (Clock& localTime,
+      std::vector<Connection*>* connections)
+  {
+    separateConnections (connections);
+
+    //MUSIC_LOGR (printconns ("NOut: ", outputConnections));
+    //MUSIC_LOGR (printconns ("NIn: ", inputConnections));
+    createNegotiationCommunicator ();
+
+    if (isLeader ())
+      {
+        collectNegotiationData (localTime.tickInterval ());
+        communicateNegotiationData ();
+        combineParameters ();
+        loopAlgorithm ();
+        distributeParameters ();
+        broadcastNegotiationData ();
+      }
+    else
+      receiveNegotiationData ();
+  }
+
+
+  void
+  TemporalNegotiatorGraph::handleLoop (
+      ANode<TemporalNegotiationData, ConnectionDescriptor> &x,
+      std::vector<AEdge<TemporalNegotiationData, ConnectionDescriptor> > & path)
+  {
+    // Search path to detect beginning of loop
+    int loop;
+    for (loop = 0; &path[loop].pre () != &x; ++loop)
+      ;
+    // Compute how much headroom we have for buffering
+    ClockState totalDelay = 0;
+    for (unsigned int c = loop; c < path.size (); ++c)
+      {
+
+        MUSIC_LOGR ("latency = " << path[c].data().accLatency << ", ti = "
+            << path[c].pre ().data().tickInterval);
+        totalDelay += path[c].data ().accLatency
+            - path[c].pre ().data ().tickInterval;
+      }
+
+    // If negative we will not be able to make it in time
+    // around the loop even without any extra buffering
+    if (totalDelay < 0)
+      {
+        std::ostringstream ostr;
+        ostr << "too short latency (" << -timebase_ * totalDelay
+            << " s) around loop: "; // << path[loop].pre().name();
+        for (unsigned int c = loop + 1; c < path.size (); ++c)
+          ostr << ", "; // << path[c].pre().name();
+        error0 (ostr.str ());
+      }
+
+    // Distribute totalDelay as allowed buffering uniformly over loop
+    // (we could do better by considering constraints form other loops)
+    int loopLength = path.size () - loop;
+    ClockState bufDelay = totalDelay / loopLength;
+    for (unsigned int c = loop; c < path.size (); ++c)
+      {
+        int allowedTicks = bufDelay / path[c].pre ().data ().tickInterval;
+        path[c].data ().maxBuffered = std::min (path[c].data ().maxBuffered,
+            allowedTicks);
+      }
+  }
+
+
+  void
+  TemporalNegotiatorGraph::setNConnections (int nConns)
+  {
+    nConnections_ = nConns;
+  }
+
+
+  int
+  TemporalNegotiatorGraph::getNConnections ()
+  {
+    return nConnections_;
+  }
+}
+#endif
diff --git a/src/version.cc b/src/version.cc
new file mode 100644
index 0000000..1a0063a
--- /dev/null
+++ b/src/version.cc
@@ -0,0 +1,29 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "music/version.hh"
+
+namespace MUSIC {
+
+  const char*
+  version ()
+  {
+    return MUSIC_VERSION;
+  }
+
+}
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
new file mode 100644
index 0000000..e692220
--- /dev/null
+++ b/testsuite/.gitignore
@@ -0,0 +1 @@
+music_tests.sh
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
new file mode 100644
index 0000000..2ed406b
--- /dev/null
+++ b/testsuite/Makefile.am
@@ -0,0 +1,9 @@
+SUBDIRS 	= unittests/catch sanitytests
+
+#runtestdir = $(bindir)
+#dist_runtest_DATA = music_tests.sh
+
+EXTRA_DIST	= $(SUBDIRS)
+
+install-data-hook:
+	@INSTALL_PROGRAM@ music_tests.sh $(DESTDIR)$(bindir)
diff --git a/testsuite/music_tests.sh.in b/testsuite/music_tests.sh.in
new file mode 100644
index 0000000..26d421a
--- /dev/null
+++ b/testsuite/music_tests.sh.in
@@ -0,0 +1,353 @@
+#!/bin/sh
+#
+# This script runs all tests that are located in the testsuite directory
+#
+
+usage ()
+{
+    if test $1 -ne 0 ; then
+	echo "Unknown option: $2"
+    fi
+    
+    cat <<EOF
+Usage: music_tests.sh [options ...]
+
+Options:
+
+    --help              Print program options and exit
+    --showme-tests      Print test names and exit
+    --output-dir=/path  Output directory (default: ./reports)
+
+EOF
+
+    exit $1
+}
+#
+# ask_results
+#
+ask_results ()
+{
+    echo "***"
+    echo "*** Please send the archived content of these directories:"
+    echo "***"
+    echo "***     - '${TEST_OUTDIR}'"
+    echo "***     - '${TEST_TMPDIR}'"
+    echo "***"
+    echo "*** to mikael@djurfeldt.com."
+    echo "***"
+    echo
+}
+
+requestedTest() 
+{
+    tn=""
+    if test -n "${TEST_NAME}" ; then
+	tn="${TEST_NAME%%*${1}*}"
+    fi
+    if test -z "${tn}" ; then
+	return 0
+    else
+	return 1
+    fi
+}
+
+list_test()
+{
+    TEST_TOTAL=$(( ${TEST_TOTAL} + 1 ))
+    echo "Test #${TEST_TOTAL} '${test_name}'"
+}
+
+# arguments: message
+bail_out ()
+{
+    echo "$1"
+    exit 1
+}
+
+# arguments: file_name expression
+portable_inplace_sed ()
+{
+    cp -f "$1" "$1.XXX"
+    sed -e "$2" "$1.XXX" > "$1"
+    rm -f "$1.XXX"
+}
+
+JUNIT_FILE=
+JUNIT_TESTS=
+JUNIT_FAILURES=
+JUNIT_CLASSNAME='core'
+
+junit_open ()
+{
+    JUNIT_FILE="${TEST_OUTDIR}/music_test_results.xml"
+    JUNIT_TESTS=0
+    JUNIT_FAILURES=0
+
+    TIME_TOTAL=0
+
+    # Be compatible with BSD date; no --rfc-3339 and :z modifier
+    timestamp="$( date -u '+%FT%T+00:00' )"
+
+    echo '<?xml version="1.0" encoding="UTF-8" ?>' > "${JUNIT_FILE}"
+
+    echo "<testsuite errors=\"0\" failures=XXX hostname=\"${INFO_HOST}\" name=\"music_test_results\" tests=XXX time=XXX timestamp=\"${timestamp}\">" >> "${JUNIT_FILE}"
+    echo '  <properties>' >> "${JUNIT_FILE}"
+    echo "    <property name=\"os.arch\" value=\"${INFO_ARCH}\" />" >> "${JUNIT_FILE}"
+    echo "    <property name=\"os.name\" value=\"${INFO_OS}\" />" >> "${JUNIT_FILE}"
+    echo "    <property name=\"os.version\" value=\"${INFO_VER}\" />" >> "${JUNIT_FILE}"
+    echo "    <property name=\"user.home\" value=\"${INFO_HOME}\" />" >> "${JUNIT_FILE}"
+    echo "    <property name=\"user.name\" value=\"${INFO_USER}\" />" >> "${JUNIT_FILE}"
+    echo '  </properties>' >> "${JUNIT_FILE}"
+}
+
+
+# arguments: classname testname [fail_message fail_trace]
+junit_write ()
+{
+    if test "x${JUNIT_FILE}" = x ; then
+        bail_out 'junit_write: report file not open, call junit_open first!'
+    fi
+
+    if test "x$1" = x || test "x$2" = x ; then
+        bail_out 'junit_write: classname and testname arguments are mandatory!'
+    fi
+
+    JUNIT_TESTS=$(( ${JUNIT_TESTS} + 1 ))
+
+    printf '%s' "  <testcase classname=\"$1\" name=\"$2\" time=\"${TIME_ELAPSED}\"" >> "${JUNIT_FILE}"
+
+    if test "x$3" != x ; then
+        echo '>' >> "${JUNIT_FILE}"
+        echo "    <failure message=\"$3\" type=\"\"><![CDATA[" >> "${JUNIT_FILE}"
+        echo "$4" | sed 's/]]>/]]>]]\&gt;<![CDATA[/' >> "${JUNIT_FILE}"
+        echo "]]></failure>" >> "${JUNIT_FILE}"
+        echo "  </testcase>" >> "${JUNIT_FILE}"
+    else
+        echo ' />' >> "${JUNIT_FILE}"
+    fi
+}
+
+junit_close ()
+{
+    if test "x${JUNIT_FILE}" = x ; then
+        bail_out 'junit_close: report file not open, call junit_open first!'
+    fi
+
+    portable_inplace_sed "${JUNIT_FILE}" "s/time=XXX/time=\"${TIME_TOTAL}\"/"
+    portable_inplace_sed "${JUNIT_FILE}" "s/tests=XXX/tests=\"${JUNIT_TESTS}\"/"
+    portable_inplace_sed "${JUNIT_FILE}" "s/failures=XXX/failures=\"${JUNIT_FAILURES}\"/"
+
+    echo '  <system-out><![CDATA[]]></system-out>' >> "${JUNIT_FILE}"
+    echo '  <system-err><![CDATA[]]></system-err>' >> "${JUNIT_FILE}"
+    echo '</testsuite>' >> "${JUNIT_FILE}"
+
+    JUNIT_FILE=
+}
+
+#arguments: run_test script_name codes_success codes_failure
+run_test()
+{
+    TEST_TOTAL=$(( ${TEST_TOTAL} + 1 ))
+
+    test_name="$1"
+    param_success="$2"
+    param_failure="$3"
+
+    msg_error=
+
+    junit_class="$( echo "${test_name}" | sed 's/.[^.]\+$//' | sed 's/\/[^/]\+$//' | sed 's/\//./' )"
+    junit_name="$( echo "${test_name}" | sed 's/^.*\/\([^/]\+\)$/\1/' )"
+
+    TEST_OUTFILE="${TEST_OUTDIR}/$( echo "${test_name##*/}" | sed 's/\.test//'  ).log"
+   
+    echo "Running test '${test_name}'..."
+    echo  >> "${TEST_LOGFILE}" "Running test '${test_name}'..."
+
+    # Generating script on fly due to possible command 
+    # incompatibility with different subshells (dash, bash, etc.)
+    
+    echo "#!/bin/sh" > "${TEST_RUNFILE}"
+    echo "set +e" >> "${TEST_RUNFILE}"
+    
+    command="'${TEST_BASEDIR}/${test_name}' > '${TEST_OUTFILE}' 2>&1"
+
+    echo "${command}" >> "${TEST_RUNFILE}"
+    echo "echo \$? > '${TEST_RETFILE}' ; exit 0" >> "${TEST_RUNFILE}"
+
+    chmod 755 "${TEST_RUNFILE}"
+    
+    time_dirty="$( /bin/sh -c "time ${TIME_PARAM} '${TEST_RUNFILE}' " 2>&1 )"
+    rm -f "${TEST_RUNFILE}"
+
+    TIME_ELAPSED="$( echo "${time_dirty}" | awk 'NR == 1 { print $2 ; }' )"
+    TIME_TOTAL="$( awk "BEGIN { print (${TIME_TOTAL} + ${TIME_ELAPSED}) ; }" )"
+
+    exit_code="$(cat "${TEST_RETFILE}")"
+    
+    sed 's/^/   > /g' "${TEST_OUTFILE}" >> "${TEST_LOGFILE}"
+
+    msg_dirty=${param_success##* ${exit_code} }
+    msg_clean=${msg_dirty%%,*}
+    if test "${msg_dirty}" != "${param_success}" ; then
+        TEST_PASSED=$(( ${TEST_PASSED} + 1 ))
+        explanation="${msg_clean}"
+        junit_failure=
+    else
+        TEST_FAILED=$(( ${TEST_FAILED} + 1 ))
+        JUNIT_FAILURES=$(( ${JUNIT_FAILURES} + 1 ))
+
+        msg_dirty=${param_failure##* ${exit_code} }
+        msg_clean=${msg_dirty%%,*}
+        if test "${msg_dirty}" != "${param_failure}" ; then
+            explanation="${msg_clean}"
+        else
+            explanation="Failed: unexpected exit code ${exit_code}"
+            msg_error="$( cat "${TEST_OUTFILE}" )"
+        fi
+
+        junit_failure="${exit_code} (${explanation})"
+    fi
+    
+    echo "...${explanation}"
+
+    echo >> "${TEST_LOGFILE}" "-> ${exit_code} (${explanation})"
+    echo >> "${TEST_LOGFILE}" "----------------------------------------"
+
+    junit_write "${JUNIT_CLASSNAME}.${junit_class}" "${junit_name}" "${junit_failure}" "$(cat "${TEST_OUTFILE}")"
+
+    # Panic on "unexpected" exit code
+    if test "x${msg_error}" != x ; then
+        echo "${msg_error}"
+        echo
+        echo "***"
+        echo "*** An unexpected exit code usually hints at a bug in the test suite!"
+        ask_results
+        exit 2
+    fi
+
+    rm -f "${TEST_OUTFILE}" "${TEST_RETFILE}"
+}
+
+while test $# -gt 0 ; do
+    case "$1" in
+	--help)
+	    usage 0
+	    ;;
+	--output-dir=*)
+	    TEST_OUTDIR="$( echo "$1" | sed 's/^--output-dir=//' )"
+	    ;;
+	--showme-tests)
+	    EXEC=list_test
+	    ;;
+	*)
+	    TEST_NAME="${TEST_NAME} $1"
+#	    usage 1 "$1"
+	    ;;
+	esac
+        shift
+done
+
+# Gather some information about the host
+INFO_ARCH="$(uname -m)"
+INFO_HOME="$(/bin/sh -c 'echo ~')"
+INFO_HOST="$(hostname -f)"
+INFO_OS="$(uname -s)"
+INFO_USER="$(whoami)"
+INFO_VER="$(uname -r)"
+
+TIME_PARAM="-p"
+/bin/sh -c "time ${TIME_PARAM} uname" >/dev/null 2>&1 || TIME_PARAM=""
+
+TIMEFORMAT=$'real %2R\nuser %2U\nsys %2S'
+export TIMEFORMAT
+
+TEST_OUTDIR=${TEST_OUTDIR:-"$( pwd )/reports"}
+TEST_NAME=${TEST_NAME:-""}
+EXEC=${EXEC:-"run_test"}
+TEST_LOGFILE="${TEST_OUTDIR}/output.log"
+TEST_RETFILE="${TEST_OUTDIR}/output.ret"
+TEST_RUNFILE="${TEST_OUTDIR}/runtest.sh"
+
+if test -d "${TEST_OUTDIR}" ; then
+    rm -rf "${TEST_OUTDIR}"
+fi
+
+mkdir "${TEST_OUTDIR}"
+
+TMPDIR=${TMPDIR:-${TEST_OUTDIR}}
+TEST_TMPDIR="$(mktemp -d "${TMPDIR:-/tmp}/music.XXXXX")"
+MUSIC_DATA_PATH="${TEST_TMPDIR}"
+export MUSIC_DATA_PATH
+
+TEST_TOTAL=0
+TEST_PASSED=0
+TEST_FAILED=0
+
+junit_open
+
+echo > "${TEST_LOGFILE}" "MUSIC v. @PACKAGE_VERSION@"
+echo >> "${TEST_LOGFILE}" "======================="
+echo >> "${TEST_LOGFILE}" "Host information:"
+echo >> "${TEST_LOGFILE}" "architeture\t:\t${INFO_ARCH}"
+echo >> "${TEST_LOGFILE}" "home directory\t:\t${INFO_HOME}"
+echo >> "${TEST_LOGFILE}" "host name\t:\t${INFO_HOST}"
+echo >> "${TEST_LOGFILE}" "system\t\t:\t${INFO_OS}"
+echo >> "${TEST_LOGFILE}" "user name\t:\t${INFO_USER}"
+echo >> "${TEST_LOGFILE}" "kernel version\t:\t${INFO_VER}"
+echo >> "${TEST_LOGFILE}" "======================="
+
+TEST_BASEDIR="@PKGEXTRABINDIR@"
+echo >> "${TEST_LOGFILE}" "Running tests from ${TEST_BASEDIR}" 
+
+CODES_SUCCESS=' 0 Success'
+CODES_FAILURE=\
+' 1 Failed: missed assertion,'
+for test_prefix in test_ launchtest ; do
+    for test_name in $(ls "${TEST_BASEDIR}" | grep "${test_prefix}") ; do
+	if requestedTest "${test_name}" ; then
+	    "$EXEC" "${test_name}" "${CODES_SUCCESS}" "${CODES_FAILURE}"
+	fi
+    done
+done
+
+TEST_BASEDIR="@PKGDATADIR@/tests"
+echo >> "${TEST_LOGFILE}" "Running tests from ${TEST_BASEDIR}" 
+
+TEST_BINDIR="@prefix@/@bindir@"
+export TEST_BINDIR
+
+TEST_EXTRABINDIR="@PKGEXTRABINDIR@"
+export TEST_EXTRABINDIR
+
+CMP="${CMP-cmp}"
+export CMP
+
+MUSIC_BINARY="@prefix@/@bindir@/MUSIC"
+export MUSIC_BINARY
+
+
+CODES_SUCCESS=' 0 Success'
+CODES_FAILURE=\
+' 2 Failed: error in tested code block,'\
+' 10 Failed: unknown error,'\
+' 15 Failed: timeout,'
+for test_ext in test ; do
+    for test_name in $(ls "${TEST_BASEDIR}" | grep ".*\.${test_ext}\$") ; do
+	if requestedTest "${test_name}"  ; then
+	    "$EXEC" "${test_name}" "${CODES_SUCCESS}" "${CODES_FAILURE}"
+	fi
+    done
+done
+
+junit_close
+
+if test ${TEST_FAILED} -gt 0 ; then
+    echo "***"
+    echo "*** There were errors detected during the run of the MUSIC test suite!"
+    ask_results
+else
+    rm -rf "${TEST_TMPDIR}"
+fi
+
+exit 0
+
diff --git a/testsuite/sanitytests/.gitignore b/testsuite/sanitytests/.gitignore
new file mode 100644
index 0000000..2c2e318
--- /dev/null
+++ b/testsuite/sanitytests/.gitignore
@@ -0,0 +1,6 @@
+clocksource
+constsource
+contdelay
+eventdelay
+launchtest
+multiport
diff --git a/testsuite/sanitytests/Makefile.am b/testsuite/sanitytests/Makefile.am
new file mode 100644
index 0000000..0869699
--- /dev/null
+++ b/testsuite/sanitytests/Makefile.am
@@ -0,0 +1,59 @@
+## Process this file with Automake to create Makefile.in
+
+ACLOCAL = $(top_srcdir)/aclocal.sh
+
+testbindir = $(libdir)/@PACKAGE@-@PACKAGE_VERSION@
+testbin_PROGRAMS = clocksource constsource contdelay eventdelay \
+		multiport launchtest
+
+#testshdir = $(datadir)/@PACKAGE@-@PACKAGE_VERSION@/tests
+#dist_testsh_DATA = events.test chain.test run_test \
+			divergence.test fork.test loop.test \
+			cloop.test const.test contclock.test \
+			launchtest.test messages.test \
+			multicomm.test multiport.test
+
+MUSIC_INCLUDE = -I$(top_srcdir)/src -I$(top_builddir)/src
+
+clocksource_SOURCES = clocksource.cc
+clocksource_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+clocksource_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+constsource_SOURCES = constsource.cc
+constsource_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+constsource_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+contdelay_SOURCES = contdelay.cc
+contdelay_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+contdelay_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+eventdelay_SOURCES = eventdelay.cc
+eventdelay_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+eventdelay_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+multiport_SOURCES = multiport.cc
+multiport_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+multiport_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+launchtest_SOURCES = launchtest.cc
+launchtest_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+launchtest_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+
+MKDEP = gcc -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+
+EXTRA_DIST = events.test chain.test run_test \
+			divergence.test fork.test loop.test \
+			cloop.test const.test contclock.test \
+			launchtest.test messages.test \
+			multicomm.test multiport.test
+
+install-data-hook:
+	mkdir -p $(DESTDIR)@PKGDATADIR@/tests
+	cd $(srcdir);\
+	@INSTALL_PROGRAM@ events.test chain.test run_test \
+			divergence.test fork.test loop.test \
+			cloop.test const.test contclock.test \
+			launchtest.test messages.test \
+			multicomm.test multiport.test \
+			  $(DESTDIR)@PKGDATADIR@/tests
\ No newline at end of file
diff --git a/testsuite/sanitytests/chain.test b/testsuite/sanitytests/chain.test
new file mode 100644
index 0000000..7aca8e3
--- /dev/null
+++ b/testsuite/sanitytests/chain.test
@@ -0,0 +1,94 @@
+#!/bin/sh
+
+NP=4
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+stoptime=1.0
+[from]
+  np=2
+  binary=${TEST_BINDIR}/eventsource
+  args=-b 2 10 ${MUSIC_DATA_PATH}/spikes
+[mid]
+  np=1
+  binary=${TEST_EXTRABINDIR}/eventdelay
+  args=-d 0.3
+[to]
+  np=1
+  binary=${TEST_BINDIR}/eventlogger
+  args=-b 2
+  from.out -> mid.in [10, ${method}]
+  mid.out -> to.in [10, ${method}]
+EOF
+}
+
+# this is input data
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes0.dat"
+# spikes
+0.0	0
+0.1	1
+0.2	2
+0.3	3
+0.4	4
+0.5	5
+0.6	6
+0.7	7
+0.8	8
+0.9	9
+EOF
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes1.dat"
+# spikes
+0.0	9
+0.1	0
+0.2	1
+0.3	2
+0.4	3
+0.5	4
+0.6	5
+0.7	6
+0.8	7
+0.9	8
+EOF
+
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+Rank 0: Event (9, 0.3) detected at 0.29
+Rank 0: Event (0, 0.3) detected at 0.29
+Rank 0: Event (1, 0.4) detected at 0.39
+Rank 0: Event (2, 0.5) detected at 0.49
+Rank 0: Event (3, 0.6) detected at 0.57
+Rank 0: Event (4, 0.7) detected at 0.67
+Rank 0: Event (5, 0.9) detected at 0.87
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
\ No newline at end of file
diff --git a/testsuite/sanitytests/clocksource.cc b/testsuite/sanitytests/clocksource.cc
new file mode 100644
index 0000000..996f090
--- /dev/null
+++ b/testsuite/sanitytests/clocksource.cc
@@ -0,0 +1,153 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <cstdlib>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+const double DEFAULT_TIMESTEP = 1e-2;
+
+double dataarray[1];
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: clocksource [OPTION...]" << std::endl
+		<< "`clocksource' sends out the current time" << std::endl
+		<< "through a MUSIC output port." << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -b, --maxbuffered TICKS maximal amount of data buffered" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+double timestep = DEFAULT_TIMESTEP;
+int    maxbuffered = 0;
+
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",    required_argument, 0, 't'},
+	  {"maxbuffered", required_argument, 0, 'b'},
+	  {"help",        no_argument,       0, 'h'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:b:h",
+			   longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg);
+	  continue;
+	case 'b':
+	  maxbuffered = atoi (optarg);
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind + 0 || argc > optind + 0)
+    usage (rank);
+}
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  
+  MPI::Intracomm comm = setup->communicator ();
+  int rank = comm.Get_rank ();
+  
+  getargs (rank, argc, argv);
+
+  MUSIC::ContOutputPort* out = setup->publishContOutput ("clock");
+  if (!out->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "clocksource port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+
+  MUSIC::ArrayData dmap (dataarray,
+			 MPI::DOUBLE,
+			 0,
+			 1);
+
+  if (maxbuffered > 0)
+    out->map (&dmap, maxbuffered);
+  else
+    out->map (&dmap);
+
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  dataarray[0] = 0.0;
+  
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+
+  for (; runtime->time () < stoptime; runtime->tick ())
+    {
+      // Use current time (valid at next tick) at exported data
+      dataarray[0] = runtime->time () + timestep;
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/testsuite/sanitytests/cloop.test b/testsuite/sanitytests/cloop.test
new file mode 100644
index 0000000..f70eb5d
--- /dev/null
+++ b/testsuite/sanitytests/cloop.test
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+NP=4
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+np=1
+stoptime=1.0
+[A]
+  binary=${TEST_EXTRABINDIR}/contdelay
+  args=-d 0.1 -b 1000
+[B]
+  binary=${TEST_EXTRABINDIR}/contdelay
+  args=-d 0.1 -b 1000
+[from]
+  binary=${TEST_EXTRABINDIR}/clocksource
+  args=-b 5
+[to]
+  binary=${TEST_BINDIR}/contsink
+
+from.clock -> A.in [1,${method}]
+A.out -> B.in [1,${method}]
+B.out -> to.contdata [1,${method}]
+B.out -> A.aux [1,${method}]
+EOF
+
+}
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+0 on 0 @0
+0 on 0 @0.01
+0 on 0 @0.02
+0 on 0 @0.03
+0 on 0 @0.04
+0 on 0 @0.05
+0 on 0 @0.06
+0 on 0 @0.07
+0 on 0 @0.08
+0 on 0 @0.09
+0 on 0 @0.1
+0 on 0 @0.11
+0 on 0 @0.12
+0 on 0 @0.13
+0 on 0 @0.14
+0 on 0 @0.15
+0 on 0 @0.16
+0 on 0 @0.17
+0 on 0 @0.18
+0 on 0 @0.19
+0 on 0 @0.2
+0 on 0 @0.21
+0 on 0 @0.22
+0.01 on 0 @0.23
+0.02 on 0 @0.24
+0.03 on 0 @0.25
+0.04 on 0 @0.26
+0.05 on 0 @0.27
+0.06 on 0 @0.28
+0.07 on 0 @0.29
+0.08 on 0 @0.3
+0.09 on 0 @0.31
+0.1 on 0 @0.32
+0.11 on 0 @0.33
+0.12 on 0 @0.34
+0.13 on 0 @0.35
+0.14 on 0 @0.36
+0.15 on 0 @0.37
+0.16 on 0 @0.38
+0.17 on 0 @0.39
+0.18 on 0 @0.4
+0.19 on 0 @0.41
+0.2 on 0 @0.42
+0.21 on 0 @0.43
+0.22 on 0 @0.44
+0.24 on 0 @0.45
+0.26 on 0 @0.46
+0.28 on 0 @0.47
+0.3 on 0 @0.48
+0.32 on 0 @0.49
+0.34 on 0 @0.5
+0.36 on 0 @0.51
+0.38 on 0 @0.52
+0.4 on 0 @0.53
+0.42 on 0 @0.54
+0.44 on 0 @0.55
+0.46 on 0 @0.56
+0.48 on 0 @0.57
+0.5 on 0 @0.58
+0.52 on 0 @0.59
+0.54 on 0 @0.6
+0.56 on 0 @0.61
+0.58 on 0 @0.62
+0.6 on 0 @0.63
+0.62 on 0 @0.64
+0.64 on 0 @0.65
+0.66 on 0 @0.66
+0.69 on 0 @0.67
+0.72 on 0 @0.68
+0.75 on 0 @0.69
+0.78 on 0 @0.7
+0.81 on 0 @0.71
+0.84 on 0 @0.72
+0.87 on 0 @0.73
+0.9 on 0 @0.74
+0.93 on 0 @0.75
+0.96 on 0 @0.76
+0.99 on 0 @0.77
+1.02 on 0 @0.78
+1.05 on 0 @0.79
+1.08 on 0 @0.8
+1.11 on 0 @0.81
+1.14 on 0 @0.82
+1.17 on 0 @0.83
+1.2 on 0 @0.84
+1.23 on 0 @0.85
+1.26 on 0 @0.86
+1.29 on 0 @0.87
+1.32 on 0 @0.88
+1.36 on 0 @0.89
+1.4 on 0 @0.9
+1.44 on 0 @0.91
+1.48 on 0 @0.92
+1.52 on 0 @0.93
+1.56 on 0 @0.94
+1.6 on 0 @0.95
+1.64 on 0 @0.96
+1.68 on 0 @0.97
+1.72 on 0 @0.98
+1.76 on 0 @0.99
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
+
+
diff --git a/testsuite/sanitytests/const.test b/testsuite/sanitytests/const.test
new file mode 100644
index 0000000..89cf805
--- /dev/null
+++ b/testsuite/sanitytests/const.test
@@ -0,0 +1,253 @@
+#!/bin/sh
+
+NP=4
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+stoptime=1.0
+[from]
+  np=2
+  binary=${TEST_EXTRABINDIR}/constsource
+[to]
+  np=2
+  binary=${TEST_BINDIR}/contsink
+  from.contdata -> to.contdata [7, ${method}]
+EOF
+
+}
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+4 5 6 on 1 @0
+4 5 6 on 1 @0.01
+4 5 6 on 1 @0.02
+4 5 6 on 1 @0.03
+4 5 6 on 1 @0.04
+4 5 6 on 1 @0.05
+4 5 6 on 1 @0.06
+4 5 6 on 1 @0.07
+4 5 6 on 1 @0.08
+4 5 6 on 1 @0.09
+4 5 6 on 1 @0.1
+4 5 6 on 1 @0.11
+4 5 6 on 1 @0.12
+4 5 6 on 1 @0.13
+4 5 6 on 1 @0.14
+4 5 6 on 1 @0.15
+4 5 6 on 1 @0.16
+4 5 6 on 1 @0.17
+4 5 6 on 1 @0.18
+4 5 6 on 1 @0.19
+4 5 6 on 1 @0.2
+4 5 6 on 1 @0.21
+4 5 6 on 1 @0.22
+4 5 6 on 1 @0.23
+4 5 6 on 1 @0.24
+4 5 6 on 1 @0.25
+4 5 6 on 1 @0.26
+4 5 6 on 1 @0.27
+4 5 6 on 1 @0.28
+4 5 6 on 1 @0.29
+4 5 6 on 1 @0.3
+4 5 6 on 1 @0.31
+4 5 6 on 1 @0.32
+4 5 6 on 1 @0.33
+4 5 6 on 1 @0.34
+4 5 6 on 1 @0.35
+4 5 6 on 1 @0.36
+4 5 6 on 1 @0.37
+4 5 6 on 1 @0.38
+4 5 6 on 1 @0.39
+4 5 6 on 1 @0.4
+4 5 6 on 1 @0.41
+4 5 6 on 1 @0.42
+4 5 6 on 1 @0.43
+4 5 6 on 1 @0.44
+4 5 6 on 1 @0.45
+4 5 6 on 1 @0.46
+4 5 6 on 1 @0.47
+4 5 6 on 1 @0.48
+4 5 6 on 1 @0.49
+4 5 6 on 1 @0.5
+4 5 6 on 1 @0.51
+4 5 6 on 1 @0.52
+4 5 6 on 1 @0.53
+4 5 6 on 1 @0.54
+4 5 6 on 1 @0.55
+4 5 6 on 1 @0.56
+4 5 6 on 1 @0.57
+4 5 6 on 1 @0.58
+4 5 6 on 1 @0.59
+4 5 6 on 1 @0.6
+4 5 6 on 1 @0.61
+4 5 6 on 1 @0.62
+4 5 6 on 1 @0.63
+4 5 6 on 1 @0.64
+4 5 6 on 1 @0.65
+4 5 6 on 1 @0.66
+4 5 6 on 1 @0.67
+4 5 6 on 1 @0.68
+4 5 6 on 1 @0.69
+4 5 6 on 1 @0.7
+4 5 6 on 1 @0.71
+4 5 6 on 1 @0.72
+4 5 6 on 1 @0.73
+4 5 6 on 1 @0.74
+4 5 6 on 1 @0.75
+4 5 6 on 1 @0.76
+4 5 6 on 1 @0.77
+4 5 6 on 1 @0.78
+4 5 6 on 1 @0.79
+4 5 6 on 1 @0.8
+4 5 6 on 1 @0.81
+4 5 6 on 1 @0.82
+4 5 6 on 1 @0.83
+4 5 6 on 1 @0.84
+4 5 6 on 1 @0.85
+4 5 6 on 1 @0.86
+4 5 6 on 1 @0.87
+4 5 6 on 1 @0.88
+4 5 6 on 1 @0.89
+4 5 6 on 1 @0.9
+4 5 6 on 1 @0.91
+4 5 6 on 1 @0.92
+4 5 6 on 1 @0.93
+4 5 6 on 1 @0.94
+4 5 6 on 1 @0.95
+4 5 6 on 1 @0.96
+4 5 6 on 1 @0.97
+4 5 6 on 1 @0.98
+4 5 6 on 1 @0.99
+0 1 2 3 on 0 @0
+0 1 2 3 on 0 @0.01
+0 1 2 3 on 0 @0.02
+0 1 2 3 on 0 @0.03
+0 1 2 3 on 0 @0.04
+0 1 2 3 on 0 @0.05
+0 1 2 3 on 0 @0.06
+0 1 2 3 on 0 @0.07
+0 1 2 3 on 0 @0.08
+0 1 2 3 on 0 @0.09
+0 1 2 3 on 0 @0.1
+0 1 2 3 on 0 @0.11
+0 1 2 3 on 0 @0.12
+0 1 2 3 on 0 @0.13
+0 1 2 3 on 0 @0.14
+0 1 2 3 on 0 @0.15
+0 1 2 3 on 0 @0.16
+0 1 2 3 on 0 @0.17
+0 1 2 3 on 0 @0.18
+0 1 2 3 on 0 @0.19
+0 1 2 3 on 0 @0.2
+0 1 2 3 on 0 @0.21
+0 1 2 3 on 0 @0.22
+0 1 2 3 on 0 @0.23
+0 1 2 3 on 0 @0.24
+0 1 2 3 on 0 @0.25
+0 1 2 3 on 0 @0.26
+0 1 2 3 on 0 @0.27
+0 1 2 3 on 0 @0.28
+0 1 2 3 on 0 @0.29
+0 1 2 3 on 0 @0.3
+0 1 2 3 on 0 @0.31
+0 1 2 3 on 0 @0.32
+0 1 2 3 on 0 @0.33
+0 1 2 3 on 0 @0.34
+0 1 2 3 on 0 @0.35
+0 1 2 3 on 0 @0.36
+0 1 2 3 on 0 @0.37
+0 1 2 3 on 0 @0.38
+0 1 2 3 on 0 @0.39
+0 1 2 3 on 0 @0.4
+0 1 2 3 on 0 @0.41
+0 1 2 3 on 0 @0.42
+0 1 2 3 on 0 @0.43
+0 1 2 3 on 0 @0.44
+0 1 2 3 on 0 @0.45
+0 1 2 3 on 0 @0.46
+0 1 2 3 on 0 @0.47
+0 1 2 3 on 0 @0.48
+0 1 2 3 on 0 @0.49
+0 1 2 3 on 0 @0.5
+0 1 2 3 on 0 @0.51
+0 1 2 3 on 0 @0.52
+0 1 2 3 on 0 @0.53
+0 1 2 3 on 0 @0.54
+0 1 2 3 on 0 @0.55
+0 1 2 3 on 0 @0.56
+0 1 2 3 on 0 @0.57
+0 1 2 3 on 0 @0.58
+0 1 2 3 on 0 @0.59
+0 1 2 3 on 0 @0.6
+0 1 2 3 on 0 @0.61
+0 1 2 3 on 0 @0.62
+0 1 2 3 on 0 @0.63
+0 1 2 3 on 0 @0.64
+0 1 2 3 on 0 @0.65
+0 1 2 3 on 0 @0.66
+0 1 2 3 on 0 @0.67
+0 1 2 3 on 0 @0.68
+0 1 2 3 on 0 @0.69
+0 1 2 3 on 0 @0.7
+0 1 2 3 on 0 @0.71
+0 1 2 3 on 0 @0.72
+0 1 2 3 on 0 @0.73
+0 1 2 3 on 0 @0.74
+0 1 2 3 on 0 @0.75
+0 1 2 3 on 0 @0.76
+0 1 2 3 on 0 @0.77
+0 1 2 3 on 0 @0.78
+0 1 2 3 on 0 @0.79
+0 1 2 3 on 0 @0.8
+0 1 2 3 on 0 @0.81
+0 1 2 3 on 0 @0.82
+0 1 2 3 on 0 @0.83
+0 1 2 3 on 0 @0.84
+0 1 2 3 on 0 @0.85
+0 1 2 3 on 0 @0.86
+0 1 2 3 on 0 @0.87
+0 1 2 3 on 0 @0.88
+0 1 2 3 on 0 @0.89
+0 1 2 3 on 0 @0.9
+0 1 2 3 on 0 @0.91
+0 1 2 3 on 0 @0.92
+0 1 2 3 on 0 @0.93
+0 1 2 3 on 0 @0.94
+0 1 2 3 on 0 @0.95
+0 1 2 3 on 0 @0.96
+0 1 2 3 on 0 @0.97
+0 1 2 3 on 0 @0.98
+0 1 2 3 on 0 @0.99
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
+
+
diff --git a/testsuite/sanitytests/constsource.cc b/testsuite/sanitytests/constsource.cc
new file mode 100644
index 0000000..d4d42e1
--- /dev/null
+++ b/testsuite/sanitytests/constsource.cc
@@ -0,0 +1,156 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <cstdlib>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+const double DEFAULT_TIMESTEP = 1e-2;
+
+double *dataarray;
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: constsource [OPTION...]" << std::endl
+		<< "`constsource' sends out constant values" << std::endl
+		<< "through a MUSIC output port." << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+double timestep = DEFAULT_TIMESTEP;
+int    localwidth = 1;
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",    required_argument, 0, 't'},
+	  {"help",        no_argument,       0, 'h'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:n:h",
+			   longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg);
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind + 0 || argc > optind + 0)
+    usage (rank);
+}
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  
+  MPI::Intracomm comm = setup->communicator ();
+  int nProcesses = comm.Get_size ();
+  int rank = comm.Get_rank ();
+  
+  getargs (rank, argc, argv);
+
+  MUSIC::ContOutputPort* out = setup->publishContOutput ("contdata");
+  if (!out->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "constsource port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  int totalWidth = out->width ();
+  int localWidth = (totalWidth-1) / nProcesses + 1;
+  int myWidth = localWidth;
+  if (rank == nProcesses - 1)	// Last processor
+    myWidth = totalWidth - (nProcesses-1) * localWidth;
+
+  dataarray = new double[myWidth];
+
+  for (int i = 0; i < myWidth; ++i)
+    dataarray[i] = rank * localWidth + i;
+
+
+  MUSIC::ArrayData dmap (dataarray,
+			 MPI::DOUBLE,
+			 rank * localWidth,
+			 myWidth);
+
+  out->map (&dmap);
+
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+
+  double time = runtime->time ();
+  while (time < stoptime)
+    {
+      runtime->tick ();
+
+      time = runtime->time ();
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/testsuite/sanitytests/contclock.test b/testsuite/sanitytests/contclock.test
new file mode 100644
index 0000000..5768ede
--- /dev/null
+++ b/testsuite/sanitytests/contclock.test
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+NP=2
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+stoptime=0.5
+[from]
+  np=1
+  binary=${TEST_EXTRABINDIR}/clocksource
+  args=-t 0.02 -b 3
+[to]
+  np=1
+  binary=${TEST_BINDIR}/contsink
+  args=-t 0.03
+  from.clock -> to.contdata [1, ${method}]
+EOF
+
+}
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+0 on 0 @0
+0.03 on 0 @0.03
+0.06 on 0 @0.06
+0.09 on 0 @0.09
+0.12 on 0 @0.12
+0.15 on 0 @0.15
+0.18 on 0 @0.18
+0.21 on 0 @0.21
+0.24 on 0 @0.24
+0.27 on 0 @0.27
+0.3 on 0 @0.3
+0.33 on 0 @0.33
+0.36 on 0 @0.36
+0.39 on 0 @0.39
+0.42 on 0 @0.42
+0.45 on 0 @0.45
+0.48 on 0 @0.48
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
+
+
diff --git a/testsuite/sanitytests/contdelay.cc b/testsuite/sanitytests/contdelay.cc
new file mode 100644
index 0000000..e1fa673
--- /dev/null
+++ b/testsuite/sanitytests/contdelay.cc
@@ -0,0 +1,189 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <vector>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+const double DEFAULT_TIMESTEP = 1e-2;
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: contdelay [OPTION...]" << std::endl
+		<< "`contdelay' receives data a MUSIC input port" << std::endl
+		<< "and sends them out after a delay" << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -d, --delay SECS        amount of delay" << std::endl
+		<< "  -b, --maxbuffer TICKS   maximal buffer" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+std::vector<MUSIC::Event> eventBuffer;
+std::vector<MUSIC::Event> overflowBuffer;
+
+double timestep = DEFAULT_TIMESTEP;
+double delay = 0.0;
+int label = -1;
+int maxbuffered = 0;
+
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",  required_argument, 0, 't'},
+	  {"delay",     required_argument, 0, 'd'},
+	  {"label",     required_argument, 0, 'L'},
+	  {"maxbuffer", required_argument, 0, 'b'},
+	  {"help",      no_argument,       0, 'h'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:d:L:b:h", longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg);
+	  continue;
+	case 'd':
+	  delay = atof(optarg);
+	  continue;
+	case 'L':
+	  label = atoi(optarg);
+	  continue;
+	case 'b':
+	  maxbuffered = atoi(optarg);
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind || argc > optind)
+    usage (rank);
+}
+
+double inData = 0.0;
+double outData = 0.0;
+double auxData = 0.0;
+
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+
+  MPI::Intracomm comm = setup->communicator ();
+  int rank = comm.Get_rank ();
+  
+  getargs (rank, argc, argv);
+
+  MUSIC::ContInputPort* in = setup->publishContInput ("in");
+  if (!in->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "contdelay input port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  MUSIC::ArrayData inMap (&inData,
+			  MPI::DOUBLE,
+			  0,
+			  1);
+  in->map (&inMap, delay, maxbuffered);
+
+
+  MUSIC::ContOutputPort* out = setup->publishContOutput ("out");
+  if (!out->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "contdelay output port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  MUSIC::ArrayData outMap (&outData,
+			   MPI::DOUBLE,
+			   0,
+			   1);
+  out->map (&outMap, maxbuffered);
+
+
+  // Optional extra input port
+  MUSIC::ContInputPort* aux = setup->publishContInput ("aux");
+
+  if (aux->isConnected ())
+    {
+      MUSIC::ArrayData auxMap (&auxData,
+			      MPI::DOUBLE,
+			      0,
+			      1);
+      aux->map (&auxMap, delay, maxbuffered);
+    }
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  for (; runtime->time () < stoptime; runtime->tick ())
+    {
+      outData = inData + auxData;
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/testsuite/sanitytests/divergence.test b/testsuite/sanitytests/divergence.test
new file mode 100644
index 0000000..f7f5c48
--- /dev/null
+++ b/testsuite/sanitytests/divergence.test
@@ -0,0 +1,90 @@
+#!/bin/sh
+
+NP=3
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+stoptime=1.0
+[from]
+  binary=${TEST_BINDIR}/eventsource
+  args=10 ${MUSIC_DATA_PATH}/spikes
+  np=1
+[to]
+  binary=${TEST_BINDIR}/eventlogger
+  args=-a
+  np=2
+  from.out -> to.in [10,${method}]
+EOF
+
+}
+
+# this is input data
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes0.dat"
+# spikes
+0.0	0
+0.1	1
+0.2	2
+0.3	3
+0.4	4
+0.5	5
+0.6	6
+0.7	7
+0.8	8
+0.9	9
+EOF
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+Rank 0: Event (0, 0) detected at 0
+Rank 0: Event (1, 0.1) detected at 0
+Rank 0: Event (2, 0.2) detected at 0
+Rank 1: Event (0, 0) detected at 0
+Rank 0: Event (3, 0.3) detected at 0
+Rank 0: Event (4, 0.4) detected at 0
+Rank 0: Event (5, 0.5) detected at 0
+Rank 0: Event (6, 0.6) detected at 0
+Rank 0: Event (7, 0.7) detected at 0
+Rank 0: Event (8, 0.8) detected at 0
+Rank 0: Event (9, 0.9) detected at 0
+Rank 1: Event (1, 0.1) detected at 0
+Rank 1: Event (2, 0.2) detected at 0
+Rank 1: Event (3, 0.3) detected at 0
+Rank 1: Event (4, 0.4) detected at 0
+Rank 1: Event (5, 0.5) detected at 0
+Rank 1: Event (6, 0.6) detected at 0
+Rank 1: Event (7, 0.7) detected at 0
+Rank 1: Event (8, 0.8) detected at 0
+Rank 1: Event (9, 0.9) detected at 0
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
+
+
diff --git a/testsuite/sanitytests/eventdelay.cc b/testsuite/sanitytests/eventdelay.cc
new file mode 100644
index 0000000..74eef3a
--- /dev/null
+++ b/testsuite/sanitytests/eventdelay.cc
@@ -0,0 +1,243 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <vector>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+const double DEFAULT_TIMESTEP = 1e-2;
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: eventdelay [OPTION...]" << std::endl
+		<< "`eventdelay' receives spikes through a MUSIC input port" << std::endl
+		<< "and relays them to an output port" << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -d, --delay SECS        amount of delay" << std::endl
+		<< "  -b, --maxbuffer TICKS   maximal buffer" << std::endl
+		<< "  -L, --label LABEL       log events using LABEL" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+std::vector<MUSIC::Event> eventBuffer;
+std::vector<MUSIC::Event> overflowBuffer;
+
+double timestep = DEFAULT_TIMESTEP;
+double delay = 0.0;
+int label = -1;
+int maxbuffered = 0;
+
+#ifdef MUSIC_LOCAL
+class MyEventHandler: public MUSIC::EventHandlerLocalIndex {
+public:
+  void operator () (double t, MUSIC::LocalIndex id)
+  {
+    eventBuffer.push_back (MUSIC::Event (t + delay, id));
+    if (label != -1)
+      std::cout << label << ":Got(" << id <<
+	", " << t + delay << ")" << std::endl;
+  }
+};
+#else
+class MyEventHandler: public MUSIC::EventHandlerGlobalIndex {
+public:
+  void operator () (double t, MUSIC::GlobalIndex id)
+  {
+    eventBuffer.push_back (MUSIC::Event (t + delay, id));
+    if (label != -1)
+      std::cout << label << ":Got(" << id <<
+	", " << t + delay << ")" << std::endl;
+  }
+};
+#endif
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",  required_argument, 0, 't'},
+	  {"delay",     required_argument, 0, 'd'},
+	  {"label",     required_argument, 0, 'L'},
+	  {"maxbuffer", required_argument, 0, 'b'},
+	  {"help",      no_argument,       0, 'h'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:d:L:b:h", longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg);
+	  continue;
+	case 'd':
+	  delay = atof(optarg);
+	  continue;
+	case 'L':
+	  label = atoi(optarg);
+	  continue;
+	case 'b':
+	  maxbuffered = atoi(optarg);
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind || argc > optind)
+    usage (rank);
+}
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+
+  MPI::Intracomm comm = setup->communicator ();
+  int nProcesses = comm.Get_size ();
+  int rank = comm.Get_rank ();
+  
+  getargs (rank, argc, argv);
+
+  MUSIC::EventInputPort* in = setup->publishEventInput ("in");
+  if (!in->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "eventdelay input port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  MUSIC::EventOutputPort* out = setup->publishEventOutput ("out");
+  if (!out->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "eventdelay output port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  // Optional extra input port
+  MUSIC::EventInputPort* aux = setup->publishEventInput ("aux");
+
+  int width = in->width ();
+    
+  MyEventHandler evhandler;
+  
+  int localWidth = width / nProcesses;
+  int myWidth = localWidth;
+
+  if (rank == nProcesses-1)
+    {
+      myWidth = localWidth;	// FIXME
+    }
+
+  MUSIC::LinearIndex indices (rank*localWidth, myWidth);
+
+  if (maxbuffered)
+    in->map (&indices, &evhandler, delay, maxbuffered);
+  else
+    in->map (&indices, &evhandler, delay);
+
+#ifdef MUSIC_LOCAL
+  out->map (&indices, MUSIC::Index::LOCAL);
+#else
+  out->map (&indices, MUSIC::Index::GLOBAL);
+#endif
+  if (aux->isConnected ())
+    {
+      if (maxbuffered)
+	aux->map (&indices, &evhandler, 0.0, maxbuffered);
+      else
+	aux->map (&indices, &evhandler, 0.0);
+    }
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  for (; runtime->time () < stoptime; runtime->tick ())
+    {
+      sort (eventBuffer.begin (), eventBuffer.end ());
+      for (std::vector<MUSIC::Event>::iterator i = eventBuffer.begin ();
+	   i != eventBuffer.end ();
+	   ++i)
+	{
+	  if (i->t < runtime->time () + timestep)
+	    {
+	      if (label != -1)
+		std::cout << label << ":Sent(" << i->id << ", "
+			  << i->t << " @" << runtime->time ()
+			  << ")" << std::endl;
+#ifdef MUSIC_LOCAL
+	      out->insertEvent (i->t, MUSIC::LocalIndex (i->id));
+#else
+	      out->insertEvent (i->t, MUSIC::GlobalIndex (i->id));
+#endif
+	    }
+	  else
+	    overflowBuffer.push_back (*i);
+	}
+      eventBuffer.clear ();
+
+      for (std::vector<MUSIC::Event>::iterator i = overflowBuffer.begin ();
+	   i != overflowBuffer.end ();
+	   ++i)
+	eventBuffer.push_back (*i);
+      overflowBuffer.clear ();
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/testsuite/sanitytests/events.test b/testsuite/sanitytests/events.test
new file mode 100755
index 0000000..08133b9
--- /dev/null
+++ b/testsuite/sanitytests/events.test
@@ -0,0 +1,82 @@
+#!/bin/sh
+
+NP=4
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+ 
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+np=2
+stoptime=1.0
+[from]
+  binary=${TEST_BINDIR}/eventsource
+  args=-b 1 10 ${MUSIC_DATA_PATH}/spikes
+[to]
+  binary=${TEST_BINDIR}/eventlogger
+  args=-b 2
+  from.out -> to.in [10, ${method}]
+EOF
+
+}
+
+
+# this is input data
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes0.dat"
+# spikes
+0.0	0
+0.1	1
+0.2	2
+0.3	3
+0.4	4
+EOF
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes1.dat"
+# spikes
+0.0	9
+0.6	5
+0.7	6
+0.8	7
+0.9	8
+EOF
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+Rank 0: Event (0, 0) detected at 0
+Rank 0: Event (1, 0.1) detected at 0.09
+Rank 0: Event (2, 0.2) detected at 0.19
+Rank 0: Event (3, 0.3) detected at 0.28
+Rank 0: Event (4, 0.4) detected at 0.39
+Rank 1: Event (5, 0.6) detected at 0.58
+Rank 1: Event (6, 0.7) detected at 0.68
+Rank 1: Event (7, 0.8) detected at 0.79
+Rank 1: Event (8, 0.9) detected at 0.89
+Rank 1: Event (9, 0) detected at 0
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+   
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+    
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
\ No newline at end of file
diff --git a/testsuite/sanitytests/fork.test b/testsuite/sanitytests/fork.test
new file mode 100644
index 0000000..2422042
--- /dev/null
+++ b/testsuite/sanitytests/fork.test
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+NP=6
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+ 
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+np=2
+stoptime=1.0
+[from]
+  binary=${TEST_BINDIR}/eventsource
+  args=10 ${MUSIC_DATA_PATH}/spikes
+[to]
+  binary=${TEST_BINDIR}/eventlogger
+  from.out -> to.in [10,${method}]
+[two]
+  binary=${TEST_BINDIR}/eventlogger
+  from.out -> two.in [10,${method}]
+EOF
+
+}
+
+# this is input data
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes0.dat"
+# spikes
+0.0	0
+0.1	1
+0.2	2
+0.3	3
+0.4	4
+EOF
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes1.dat"
+# spikes
+0.0	9
+0.6	5
+0.7	6
+0.8	7
+0.9	8
+EOF
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+Rank 0: Event (0, 0) detected at 0
+Rank 0: Event (1, 0.1) detected at 0
+Rank 0: Event (2, 0.2) detected at 0
+Rank 0: Event (3, 0.3) detected at 0
+Rank 0: Event (4, 0.4) detected at 0
+Rank 0: Event (0, 0) detected at 0
+Rank 0: Event (1, 0.1) detected at 0
+Rank 0: Event (2, 0.2) detected at 0
+Rank 0: Event (3, 0.3) detected at 0
+Rank 0: Event (4, 0.4) detected at 0
+Rank 1: Event (9, 0) detected at 0
+Rank 1: Event (5, 0.6) detected at 0
+Rank 1: Event (6, 0.7) detected at 0
+Rank 1: Event (7, 0.8) detected at 0
+Rank 1: Event (8, 0.9) detected at 0
+Rank 1: Event (9, 0) detected at 0
+Rank 1: Event (5, 0.6) detected at 0
+Rank 1: Event (6, 0.7) detected at 0
+Rank 1: Event (7, 0.8) detected at 0
+Rank 1: Event (8, 0.9) detected at 0
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+   
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+    
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
\ No newline at end of file
diff --git a/testsuite/sanitytests/launchtest.cc b/testsuite/sanitytests/launchtest.cc
new file mode 100644
index 0000000..bba96e0
--- /dev/null
+++ b/testsuite/sanitytests/launchtest.cc
@@ -0,0 +1,20 @@
+#include <music.hh>
+
+#include <iostream>
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* musicSetup = new MUSIC::Setup (argc, argv);
+  MPI::Intracomm comm = musicSetup->communicator ();
+  int rank = comm.Get_rank ();
+  double param;
+  if (!musicSetup->config ("param", &param))
+    param = -1.0;
+  std::cout << "rank=" << rank << ":param=" << param;
+  for (int i = 0; i < argc; ++i)
+    std::cout << ':' << argv[i];
+  std::cout << std::endl;
+  MPI_Finalize ();
+  return 0;
+}
diff --git a/testsuite/sanitytests/launchtest.test b/testsuite/sanitytests/launchtest.test
new file mode 100644
index 0000000..f6ae9af
--- /dev/null
+++ b/testsuite/sanitytests/launchtest.test
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+NP=6
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+binary=${TEST_EXTRABINDIR}/launchtest
+np=3
+[1]
+  args=hej du glade
+  param=1.0
+[2]
+  args=ta en spade
+  param=2.0
+  1.as1 -> 2.bd1
+  2.bd2 <- 1.as2 # asd
+  bd2 -> 2.as2 [12,${method}]
+EOF
+
+}
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
+
+
diff --git a/testsuite/sanitytests/loop.test b/testsuite/sanitytests/loop.test
new file mode 100644
index 0000000..574d712
--- /dev/null
+++ b/testsuite/sanitytests/loop.test
@@ -0,0 +1,244 @@
+#!/bin/sh
+
+NP=4
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+np=1
+stoptime=1.1
+[A]
+  binary=${TEST_BINARY}/eventdelay
+  args=-d 0.1 -L 1 -b 2
+[B]
+  binary=${TEST_BINARY}/eventdelay
+  args=-d 0.1 -L 2 -b 2
+[from]
+  binary=${TEST_BINARY}/eventsource
+  args=-b 5 10 ${MUSIC_DATA_PATH}/spikes
+[to]
+  binary=${TEST_BINARY}/eventlogger
+  args=-b 5
+
+from.out -> A.in [10, ${method}]
+A.out -> B.in [10, ${method}]
+B.out -> A.aux [10, ${method}]
+B.out -> to.in [10, ${method}]
+EOF
+
+}
+
+# this is input data
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes0.dat"
+# spikes
+0.0	0
+0.1	1
+0.2	2
+0.3	3
+0.4	4
+0.5	5
+0.6	6
+0.7	7
+0.8	8
+0.9	9
+EOF
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+1:Got(0, 0.1)
+1:Got(1, 0.2)
+1:Sent(0, 0.1 @0.1)
+2:Got(0, 0.2)
+2:Sent(0, 0.2 @0.2)
+1:Got(0, 0.3)
+1:Sent(1, 0.2 @0.2)
+1:Got(2, 0.3)
+2:Got(1, 0.3)
+2:Sent(1, 0.3 @0.3)
+1:Got(1, 0.4)
+1:Sent(0, 0.3 @0.3)
+1:Sent(2, 0.3 @0.3)
+2:Got(0, 0.4)
+1:Got(3, 0.4)
+2:Got(2, 0.4)
+Rank 0: Event (0, 0.2) detected at 0.19
+Rank 0: Event (1, 0.3) detected at 0.29
+2:Sent(0, 0.4 @0.4)
+2:Sent(2, 0.4 @0.4)
+1:Got(0, 0.5)
+1:Got(2, 0.5)
+Rank 0: Event (0, 0.4) detected at 0.39
+Rank 0: Event (2, 0.4) detected at 0.39
+1:Sent(1, 0.4 @0.4)
+2:Got(1, 0.5)
+2:Got(3, 0.5)
+1:Sent(3, 0.4 @0.4)
+1:Got(4, 0.5)
+2:Sent(1, 0.5 @0.5)
+2:Sent(3, 0.5 @0.5)
+Rank 0: Event (1, 0.5) detected at 0.49
+Rank 0: Event (3, 0.5) detected at 0.49
+1:Got(1, 0.6)
+1:Got(3, 0.6)
+1:Sent(0, 0.5 @0.5)
+1:Sent(2, 0.5 @0.5)
+1:Sent(4, 0.5 @0.5)
+2:Got(0, 0.6)
+2:Got(2, 0.6)
+2:Got(4, 0.6)
+1:Got(0, 0.7)
+2:Sent(0, 0.6 @0.59)
+2:Sent(2, 0.6 @0.59)
+2:Sent(4, 0.6 @0.59)
+Rank 0: Event (0, 0.6) detected at 0.54
+Rank 0: Event (2, 0.6) detected at 0.54
+1:Got(2, 0.7)
+1:Got(4, 0.7)
+Rank 0: Event (4, 0.6) detected at 0.54
+1:Got(5, 0.6)
+1:Got(6, 0.7)
+1:Sent(1, 0.6 @0.59)
+1:Sent(3, 0.6 @0.59)
+1:Sent(5, 0.6 @0.59)
+2:Got(1, 0.7)
+2:Got(3, 0.7)
+2:Got(5, 0.7)
+2:Sent(1, 0.7 @0.69)
+2:Sent(3, 0.7 @0.69)
+2:Sent(5, 0.7 @0.69)
+1:Got(1, 0.8)
+1:Got(3, 0.8)
+Rank 0: Event (1, 0.7) detected at 0.64
+Rank 0: Event (3, 0.7) detected at 0.64
+1:Got(5, 0.8)
+1:Sent(0, 0.7 @0.69)
+1:Sent(2, 0.7 @0.69)
+1:Sent(4, 0.7 @0.69)
+1:Sent(6, 0.7 @0.69)
+1:Got(7, 0.8)
+Rank 0: Event (5, 0.7) detected at 0.64
+2:Got(0, 0.8)
+2:Got(2, 0.8)
+2:Got(4, 0.8)
+2:Got(6, 0.8)
+2:Sent(0, 0.8 @0.79)
+2:Sent(2, 0.8 @0.79)
+2:Sent(4, 0.8 @0.79)
+2:Sent(6, 0.8 @0.79)
+Rank 0: Event (0, 0.8) detected at 0.74
+Rank 0: Event (2, 0.8) detected at 0.74
+Rank 0: Event (4, 0.8) detected at 0.74
+Rank 0: Event (6, 0.8) detected at 0.74
+1:Got(0, 0.9)
+1:Got(2, 0.9)
+1:Got(4, 0.9)
+1:Got(6, 0.9)
+1:Sent(1, 0.8 @0.79)
+1:Sent(3, 0.8 @0.79)
+1:Sent(5, 0.8 @0.79)
+1:Sent(7, 0.8 @0.79)
+2:Got(1, 0.9)
+2:Got(3, 0.9)
+2:Got(5, 0.9)
+2:Got(7, 0.9)
+1:Got(8, 0.9)
+2:Sent(1, 0.9 @0.89)
+2:Sent(3, 0.9 @0.89)
+2:Sent(5, 0.9 @0.89)
+2:Sent(7, 0.9 @0.89)
+1:Got(1, 1)
+1:Got(3, 1)
+1:Got(5, 1)
+1:Got(7, 1)
+1:Sent(0, 0.9 @0.89)
+Rank 0: Event (1, 0.9) detected at 0.84
+Rank 0: Event (3, 0.9) detected at 0.84
+1:Sent(2, 0.9 @0.89)
+1:Sent(4, 0.9 @0.89)
+1:Sent(6, 0.9 @0.89)
+1:Sent(8, 0.9 @0.9)
+Rank 0: Event (5, 0.9) detected at 0.84
+1:Got(9, 1)
+Rank 0: Event (7, 0.9) detected at 0.84
+2:Got(0, 1)
+2:Got(2, 1)
+2:Got(4, 1)
+2:Got(6, 1)
+2:Got(8, 1)
+2:Sent(0, 1 @0.99)
+2:Sent(2, 1 @0.99)
+2:Sent(4, 1 @0.99)
+2:Sent(6, 1 @0.99)
+1:Got(0, 1.1)
+1:Got(2, 1.1)
+1:Got(4, 1.1)
+2:Sent(8, 1 @1)
+Rank 0: Event (0, 1) detected at 0.94
+1:Got(6, 1.1)
+1:Sent(1, 1 @0.99)
+Rank 0: Event (2, 1) detected at 0.94
+Rank 0: Event (4, 1) detected at 0.94
+Rank 0: Event (6, 1) detected at 0.94
+1:Sent(3, 1 @0.99)
+1:Sent(5, 1 @0.99)
+1:Sent(7, 1 @0.99)
+1:Got(8, 1.1)
+1:Sent(9, 1 @1)
+2:Got(1, 1.1)
+Rank 0: Event (8, 1) detected at 0.99
+2:Got(3, 1.1)
+2:Got(5, 1.1)
+2:Got(7, 1.1)
+2:Got(9, 1.1)
+2:Sent(1, 1.1 @1.09)
+2:Sent(3, 1.1 @1.09)
+2:Sent(5, 1.1 @1.09)
+2:Sent(7, 1.1 @1.09)
+1:Got(1, 1.2)
+1:Got(3, 1.2)
+1:Got(5, 1.2)
+1:Got(7, 1.2)
+1:Sent(0, 1.1 @1.09)
+1:Sent(2, 1.1 @1.09)
+1:Sent(4, 1.1 @1.09)
+1:Sent(6, 1.1 @1.09)
+Rank 0: Event (1, 1.1) detected at 1.04
+Rank 0: Event (3, 1.1) detected at 1.04
+Rank 0: Event (5, 1.1) detected at 1.04
+Rank 0: Event (7, 1.1) detected at 1.04
+2:Got(0, 1.2)
+2:Got(2, 1.2)
+2:Got(4, 1.2)
+2:Got(6, 1.2)
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
+
+
diff --git a/testsuite/sanitytests/messages.test b/testsuite/sanitytests/messages.test
new file mode 100644
index 0000000..15dcb6e
--- /dev/null
+++ b/testsuite/sanitytests/messages.test
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+NP=4
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+ 
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+np=2
+stoptime=1.0
+[from]
+  binary=${TEST_BINDIR}/messagesource
+  args=-b 1 ${MUSIC_DATA_PATH}/messages
+[to]
+  binary=${TEST_BINDIR}/eventlogger
+  args=-b 2
+  from.out -> to.message [10, ${method}]
+EOF
+}
+
+
+# this is input data
+cat <<\EOF > "${MUSIC_DATA_PATH}/messages0.dat"
+0.3	Hello
+0.7	!
+EOF
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/messages1.dat"
+0.5	World
+0.71	Hello World
+0.72	!
+EOF
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+Rank 0: Message (0.3, Hello) detected at 0.28
+Rank 1: Message (0.3, Hello) detected at 0.28
+Rank 0: Message (0.5, World) detected at 0.49
+Rank 1: Message (0.5, World) detected at 0.49
+Rank 0: Message (0.7, !) detected at 0.68
+Rank 1: Message (0.7, !) detected at 0.68
+Rank 0: Message (0.71, Hello World) detected at 0.69
+Rank 1: Message (0.71, Hello World) detected at 0.69
+Rank 0: Message (0.72, !) detected at 0.7
+Rank 1: Message (0.72, !) detected at 0.7
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+   
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+    
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
\ No newline at end of file
diff --git a/testsuite/sanitytests/multicomm.test b/testsuite/sanitytests/multicomm.test
new file mode 100644
index 0000000..cbcf8dc
--- /dev/null
+++ b/testsuite/sanitytests/multicomm.test
@@ -0,0 +1,99 @@
+#!/bin/sh
+
+NP=8
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+ 
+write_configuration ()
+{
+
+method=$1
+echo "Communication method: ${method}"
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+stoptime=1.0
+np=2
+[S0]
+  binary=${TEST_BINDIR}/eventsource
+  args=--out out0 10 ${MUSIC_DATA_PATH}/spikes
+[S1]
+  binary=${TEST_BINDIR}/eventsource
+  args=--out out1 10 ${MUSIC_DATA_PATH}/spikes
+[R0]
+  binary=${TEST_BINDIR}/eventlogger
+  args=--in in0
+[R1]
+  binary=${TEST_BINDIR}/eventlogger
+  args=--in in1
+S0.out0 -> R0.in0 [10, ${method}]
+S1.out1 -> R1.in1 [10, ${method}]
+EOF
+
+}
+
+
+# this is input data
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes0.dat"
+# spikes
+0.0	0
+0.1	1
+0.2	2
+0.3	3
+0.4	4
+EOF
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/spikes1.dat"
+# spikes
+0.0	9
+0.6	5
+0.7	6
+0.8	7
+0.9	8
+EOF
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+Rank 0: Event (0, 0) detected at 0
+Rank 0: Event (1, 0.1) detected at 0
+Rank 0: Event (2, 0.2) detected at 0
+Rank 0: Event (3, 0.3) detected at 0
+Rank 0: Event (4, 0.4) detected at 0
+Rank 1: Event (9, 0) detected at 0
+Rank 1: Event (5, 0.6) detected at 0
+Rank 1: Event (6, 0.7) detected at 0
+Rank 1: Event (7, 0.8) detected at 0
+Rank 1: Event (8, 0.9) detected at 0
+Rank 0: Event (0, 0) detected at 0
+Rank 0: Event (1, 0.1) detected at 0
+Rank 0: Event (2, 0.2) detected at 0
+Rank 0: Event (3, 0.3) detected at 0
+Rank 0: Event (4, 0.4) detected at 0
+Rank 1: Event (9, 0) detected at 0
+Rank 1: Event (5, 0.6) detected at 0
+Rank 1: Event (6, 0.7) detected at 0
+Rank 1: Event (7, 0.8) detected at 0
+Rank 1: Event (8, 0.9) detected at 0
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+   
+for method in point-to-point collective ; do
+    write_configuration "${method}"
+    
+    run_test "${NP}" "${music_conf}"
+    exit_code=$?
+    
+    if test "${exit_code}" -gt 0 ; then
+	exit "${exit_code}"
+    fi
+done
+
+exit 0
\ No newline at end of file
diff --git a/testsuite/sanitytests/multiport.cc b/testsuite/sanitytests/multiport.cc
new file mode 100644
index 0000000..00fbcc3
--- /dev/null
+++ b/testsuite/sanitytests/multiport.cc
@@ -0,0 +1,441 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <cstdlib>
+#include <cmath>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+#include <music/error.hh>
+
+const double DEFAULT_TIMESTEP = 1e-2;
+const double DEFAULT_FREQUENCY = 10.0; // Hz
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: multiport [OPTION...]" << std::endl
+		<< "`eventgenerator' generates spikes from a Poisson distribution." << std::endl << std:: endl
+		<< "  -t, --timestep  TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -b, --maxbuffered TICKS  maximal amount of data buffered" << std::endl
+		<< "  -f, --frequency FREQ     average frequency (default " << DEFAULT_FREQUENCY << " Hz)" << std::endl
+		<< "  -m, --imaptype  TYPE     linear (default) or roundrobin" << std::endl
+		<< "  -i, --indextype TYPE     global (default) or local" << std::endl
+		<< "      --out NAME:WIDTH     name and width of an output port" << std::endl
+		<< "      --in  NAME:WIDTH     name and width of input port" << std::endl
+		<< "  -h, --help               print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+double timestep = DEFAULT_TIMESTEP;
+int    maxbuffered = 0;
+double freq = DEFAULT_FREQUENCY;
+string imaptype = "linear";
+string indextype = "global";
+
+double
+negexp (double m)
+{
+  return - m * log (drand48 ());
+}
+
+class Port {
+protected:
+  MUSIC::Setup* setup_;
+  std::string name_;
+  int width_;
+
+public:
+  Port (MUSIC::Setup* setup, std::string name, int width)
+    : setup_ (setup), name_ (name), width_ (width) { }
+};
+
+class OutputPort : public Port {
+  MUSIC::EventOutputPort* port_;
+  MUSIC::Index::Type type;
+  std::vector<MUSIC::GlobalIndex> ids;
+  std::vector<double> nextSpike;
+  double m;
+
+public:
+  OutputPort (MUSIC::Setup* setup, std::string name, int width)
+    : Port (setup, name, width) { }
+
+  void publish ()
+  {
+    port_ = setup_->publishEventOutput (name_);
+    if (!port_->isConnected ())
+      {
+	if (setup_->communicator ().Get_rank () == 0)
+	  std::cerr << "multiport port is not connected" << std::endl;
+	setup_->communicator ().Abort (1);
+      }
+  }
+
+  void map (int maxbuffered, std::string imaptype, std::string indextype)
+  {
+    MPI::Intracomm comm = setup_->communicator ();
+    int rank = comm.Get_rank ();
+    int nProcesses = comm.Get_size ();
+
+    if (indextype == "global")
+      type = MUSIC::Index::GLOBAL;
+    else
+      type = MUSIC::Index::LOCAL;
+    
+    if (imaptype == "linear")
+      {
+	int nUnitsPerProcess = width_ / nProcesses;
+	int nLocalUnits = nUnitsPerProcess;
+	int rest = width_ % nProcesses;
+	int firstId = nUnitsPerProcess * rank;
+	if (rank < rest)
+	  {
+	    firstId += rank;
+	    nLocalUnits += 1;
+	  }
+	else
+	  firstId += rest;
+	for (int i = 0; i < nLocalUnits; ++i)
+	  ids.push_back (firstId + i);
+	MUSIC::LinearIndex indices (firstId, nLocalUnits);
+      
+	if (maxbuffered > 0)
+	  port_->map (&indices, type, maxbuffered);
+	else
+	  port_->map (&indices, type);
+      }
+    else
+      {
+	for (int i = rank; i < width_; i += nProcesses)
+	  ids.push_back (i);
+	MUSIC::PermutationIndex indices (&ids.front (), ids.size ());
+	if (maxbuffered > 0)
+	  port_->map (&indices, type, maxbuffered);
+	else
+	  port_->map (&indices, type);
+      }
+  }
+
+  void init (double freq)
+  {
+    m = 1.0 / freq;
+    for (unsigned int i = 0; i < ids.size (); ++i)
+      nextSpike.push_back (negexp (m));
+  }
+
+  void tick (double nextTime)
+  {
+    if (type == MUSIC::Index::GLOBAL)
+      {
+	for (unsigned int i = 0; i < ids.size (); ++i)
+	  while (nextSpike[i] < nextTime)
+	    {
+	      port_->insertEvent (nextSpike[i],
+				  MUSIC::GlobalIndex (ids[i]));
+	      nextSpike[i] += negexp (m);
+	    }
+      }
+    else
+      {
+	for (unsigned int i = 0; i < ids.size (); ++i)
+	  while (nextSpike[i] < nextTime)
+	    {
+	      port_->insertEvent (nextSpike[i],
+				  MUSIC::LocalIndex (i));
+	      nextSpike[i] += negexp (m);
+	    }
+      }
+  }
+};
+
+class MyEventHandlerGlobal : public MUSIC::EventHandlerGlobalIndex {
+public:
+  void operator () (double t, MUSIC::GlobalIndex id)
+  {
+    //eventBuffer.push_back (MUSIC::Event (t, id));
+  }
+};
+
+class MyEventHandlerLocal: public MUSIC::EventHandlerLocalIndex {
+public:
+  void operator () (double t, MUSIC::LocalIndex id)
+  {
+    //eventBuffer.push_back (MUSIC::Event (t, id));
+  }
+};
+
+class InputPort : public Port {
+  MUSIC::EventInputPort* port_;
+  MyEventHandlerGlobal evhandlerGlobal;
+  MyEventHandlerLocal evhandlerLocal;
+
+public:
+  InputPort (MUSIC::Setup* setup, std::string name, int width)
+    : Port (setup, name, width) { }
+
+  void publish ()
+  {
+    port_ = setup_->publishEventInput (name_);
+    if (!port_->isConnected ())
+      {
+	if (setup_->communicator ().Get_rank () == 0)
+	  std::cerr << "multiport port is not connected" << std::endl;
+	setup_->communicator ().Abort (1);
+      }
+  }
+
+  void map (std::string imaptype, std::string indextype)
+  {
+    MPI::Intracomm comm = setup_->communicator ();
+    int rank = comm.Get_rank ();
+    int nProcesses = comm.Get_size ();
+
+    if (imaptype == "linear")
+      {
+	int nUnitsPerProcess = width_ / nProcesses;
+	int nLocalUnits = nUnitsPerProcess;
+	int rest = width_ % nProcesses;
+	int firstId = nUnitsPerProcess * rank;
+	if (rank < rest)
+	  {
+	    firstId += rank;
+	    nLocalUnits += 1;
+	  }
+	else
+	  firstId += rest;
+	MUSIC::LinearIndex indices (firstId, nLocalUnits);
+
+	if (indextype == "global")
+	  port_->map (&indices, &evhandlerGlobal, 0.1);
+	else
+	  port_->map (&indices, &evhandlerLocal, 0.0);
+      }
+    else
+      {
+	std::vector<MUSIC::GlobalIndex> v;
+	for (int i = rank; i < width_; i += nProcesses)
+	  v.push_back (i);
+	MUSIC::PermutationIndex indices (&v.front (), v.size ());
+
+	if (indextype == "global")
+	  port_->map (&indices, &evhandlerGlobal, 0.0);
+	else
+	  port_->map (&indices, &evhandlerLocal, 0.0);
+      }
+  }
+};
+
+std::vector<OutputPort*> outputPort;
+
+void
+makeOutput (MUSIC::Setup* setup, std::string name, int width)
+{
+  outputPort.push_back (new OutputPort (setup, name, width));
+}
+
+std::vector<InputPort*> inputPort;
+
+void
+makeInput (MUSIC::Setup* setup, std::string name, int width)
+{
+  inputPort.push_back (new InputPort (setup, name, width));
+}
+
+void
+parsePort (MUSIC::Setup* setup,
+	   std::string s,
+	   void (*makePort) (MUSIC::Setup* setup, std::string name, int width))
+{
+  std::istringstream is (s);
+  char name[80];
+  if (!is.getline (name, 80, ':'))
+    MUSIC::error ("couldn't parse port name");
+  int width;
+  if (!(is >> width))
+    MUSIC::error ("couldn't parse port width");
+  makePort (setup, name, width);
+}
+
+void
+getargs (MUSIC::Setup* setup, int argc, char* argv[])
+{
+  int rank = setup->communicator ().Get_rank ();
+
+  enum { OUT, IN };
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",  required_argument, 0, 't'},
+	  {"maxbuffered", required_argument, 0, 'b'},
+	  {"frequency", required_argument, 0, 'f'},
+	  {"imaptype",  required_argument, 0, 'm'},
+	  {"indextype", required_argument, 0, 'i'},
+	  {"help",      no_argument,       0, 'h'},
+	  {"out",	required_argument, 0, OUT},
+	  {"in",	required_argument, 0, IN},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:b:f:m:i:h", longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg); // NOTE: could do error checking
+	  continue;
+	case 'b':
+	  maxbuffered = atoi (optarg);
+	  continue;
+	case 'f':
+	  freq = atof (optarg); // NOTE: error checking here as well
+	  continue;
+	case 'm':
+	  imaptype = optarg;
+	  if (imaptype != "linear" && imaptype != "roundrobin")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case 'i':
+	  indextype = optarg;
+	  if (indextype != "global" && indextype != "local")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case OUT:
+	  parsePort (setup, optarg, makeOutput);
+	  continue;
+	case IN:
+	  parsePort (setup, optarg, makeInput);
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc != optind)
+    usage (rank);
+}
+
+#include <cassert>
+
+void
+errhandler (MPI_Comm* comm, int* error, ...)
+{
+  assert (0);
+}
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  MPI_Errhandler errh;
+  MPI_Errhandler_create (errhandler, &errh);
+  MPI_Comm_set_errhandler (MPI_COMM_WORLD, errh);
+  
+  MPI::Intracomm comm = setup->communicator ();
+  int rank = comm.Get_rank ();
+  
+  getargs (setup, argc, argv);
+
+  for (std::vector<InputPort*>::iterator i = inputPort.begin ();
+       i != inputPort.end ();
+       ++i)
+    (*i)->publish ();
+
+  for (std::vector<OutputPort*>::iterator i = outputPort.begin ();
+       i != outputPort.end ();
+       ++i)
+    (*i)->publish ();
+
+  for (std::vector<InputPort*>::iterator i = inputPort.begin ();
+       i != inputPort.end ();
+       ++i)
+    (*i)->map (imaptype, indextype);
+
+  for (std::vector<OutputPort*>::iterator i = outputPort.begin ();
+       i != outputPort.end ();
+       ++i)
+    (*i)->map (maxbuffered, imaptype, indextype);
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  srand48 (rank);		// Use different seeds
+
+  for (std::vector<OutputPort*>::iterator i = outputPort.begin ();
+       i != outputPort.end ();
+       ++i)
+    (*i)->init (freq);
+
+  double time = runtime->time ();
+  while (time < stoptime)
+    {
+      double nextTime = time + timestep;
+
+      for (std::vector<OutputPort*>::iterator i = outputPort.begin ();
+	   i != outputPort.end ();
+	   ++i)
+	(*i)->tick (nextTime);
+      
+      // Make data available for other programs
+      runtime->tick ();
+
+      time = runtime->time ();
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/testsuite/sanitytests/multiport.test b/testsuite/sanitytests/multiport.test
new file mode 100644
index 0000000..62326b9
--- /dev/null
+++ b/testsuite/sanitytests/multiport.test
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+NP=4
+music_conf="$( echo "${0##*/}" | sed 's/\.test//'  ).music"
+
+abspath="$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"
+path="`dirname $abspath`"
+
+. ${path}/run_test
+
+# this is music configuration file
+cat <<EOF > "${MUSIC_DATA_PATH}/${music_conf}"
+stoptime=1.0
+[A]
+  binary=${TEST_EXTRABINDIR}/multiport
+  args=--in in0:2640 --in in1:2640 --in in2:1 --out out0:968 --out out1:968 --out out2:1 --out out3:1
+  np=2
+[B]
+  binary=${TEST_EXTRABINDIR}/multiport
+  args=--in in0:1 --out out0:2640 --out out1:2640 --out out2:1
+  np=1
+[C]
+  binary=${TEST_EXTRABINDIR}/multiport
+  args=--in in0:968 --in in1:968 --in in2:1 --in in3:1 --out out0:1
+  np=1
+B.out0 -> A.in0 [2640, collective]
+B.out1 -> A.in1 [2640, collective]
+B.out2 -> A.in2 [1,collective]
+A.out0 -> C.in0 [968,collective]
+A.out1 -> C.in1 [968,collective]
+A.out2 -> C.in2 [1,collective]
+A.out3 -> C.in3 [1,collective]
+C.out0 -> B.in0 [1,collective]
+EOF
+
+# this is the output we should expect to see
+cat <<\EOF > "${MUSIC_DATA_PATH}/ok"
+EOF
+# sort the file using locale specified by current environment
+sort "${MUSIC_DATA_PATH}/ok" -o "${MUSIC_DATA_PATH}/ok"
+
+cat <<\EOF > "${MUSIC_DATA_PATH}/errok"
+EOF
+
+run_test "${NP}" "${music_conf}"
+exit_code=$?
+
+if test "${exit_code}" -gt 0 ; then
+   exit "${exit_code}"
+fi
+
+exit 0
+
+
diff --git a/testsuite/sanitytests/run_test b/testsuite/sanitytests/run_test
new file mode 100644
index 0000000..7e1a7ee
--- /dev/null
+++ b/testsuite/sanitytests/run_test
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+run_test ()
+{
+    np=$1
+    test_name=$2
+    if [ $# -eq 3 ]; then
+      timeout=$3
+    else
+      timeout=4
+    fi
+
+    if ! $( timeout $timeout sh -c "${MUSIC_BINARY} ${np} ${MUSIC_DATA_PATH}/${test_name} 2> ${MUSIC_DATA_PATH}/err | sort -o ${MUSIC_DATA_PATH}/out"); then
+        echo "...TIMEOUT"
+	echo "......given:" 
+	cat "${MUSIC_DATA_PATH}/out" 
+	return 15
+    fi
+ 
+    if ${CMP} -s "${MUSIC_DATA_PATH}/out" "${MUSIC_DATA_PATH}/ok" ; then
+	echo "...OK"
+    else
+	echo "...FAILED"
+	echo "......given:" 
+	cat "${MUSIC_DATA_PATH}/out" 
+	echo "......expected:"
+	cat "${MUSIC_DATA_PATH}/ok"
+	echo "......error:"
+	cat "${MUSIC_DATA_PATH}/err"
+	return 2
+    fi
+
+    if "$CMP" -s "${MUSIC_DATA_PATH}/err" "${MUSIC_DATA_PATH}/errok"; then
+	:
+    else
+	echo "err:" >&2
+	cat "${MUSIC_DATA_PATH}/err" >&2
+	echo "errok:" >&2
+	cat "${MUSIC_DATA_PATH}/errok" >&2
+	return 10
+    fi
+   return 0
+}
diff --git a/testsuite/test_old/ChangeLog b/testsuite/test_old/ChangeLog
new file mode 100644
index 0000000..3d106fc
--- /dev/null
+++ b/testsuite/test_old/ChangeLog
@@ -0,0 +1,167 @@
+2014-05-28  Ekaterina Brocke  <brocke@kth.se>
+
+	* test folder is renamed to sanitytests and moved to testsuite/
+
+2012-09-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventdelay.cc: Don't log events if not given -L option.
+
+2012-08-23  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* multicomm.music: New file. Tests the case with two connector
+	pairs.
+
+	* divergence.music: New file. Tests the case where multiple
+	receiving ranks listens to the same sources.
+
+	* eventlogger.cc: Added option -a/--all meaning map all indices in
+	all ranks; Added options --in and --message-in for specifying
+	event input and message input port names; Changed default message
+	port name to "message".
+
+2010-07-28  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.7
+
+2009-10-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.6
+
+2009-10-24  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.5
+
+2009-04-01  Mikael Djurfeldt  <djurfeldt@nada.kth.se>
+
+	* Release 1.0.4
+
+2009-03-14  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* messagesource.cc, messages.music, messages0.dat, messages1.dat:
+	New files.
+
+	* Makefile.am (noinst_PROGRAMS): Added messagesource.
+	(EXTRA_DIST): Added messages.music.
+
+	* eventlogger.cc: Added support for messages.
+
+2009-03-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.3
+
+2009-03-12  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.2
+
+2009-03-11  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am: Automatically build all test programs (but don't
+	install them).
+	(EXTRA_DIST): Added cloop.music.
+
+2009-03-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.1
+
+2009-03-07  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* events.music: Removed absolute paths from binaries.
+
+2009-03-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am: Don't install waveproducer/waveconsumer example.
+
+2009-03-05  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* constsource.cc (main): Initialize loop variable i.
+
+	* contdelay.cc (getargs): Use atof instead of atoi for option -d.
+
+2009-03-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0
+
+2009-02-19  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventlogger.cc: Log time of event as well as time of reception.
+
+2009-02-10  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventlogger.cc: Added options --acclatency and --maxbuffered.
+
+2008-12-02  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Switch to CamelCase.
+
+2008-11-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventlogger.cc: Print error message if port width not specified.
+
+2008-11-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventlogger.cc, events.music: Input port renamed from "eventlog"
+	to "in".
+
+2008-11-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventlogger.cc: Added better argument handling, including
+	options; Bugfix: Don't pass pointers to automatic event handlers
+	to map.
+
+	* events.music: Removed index map type argument (which is now an
+	option).
+
+2008-10-14  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventlogger.cc: Check that port is connected before mapping it.
+
+2008-10-10  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventlogger.cc: Updated to use global_index.
+
+2008-02-01  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am (waveproducer_SOURCES, waveproducer_CXXFLAGS,
+	waveproducer_LDADD): Renamed from wavegenerator_SOURCES,
+	wavegenerator_CXXFLAGS, wavegenerator_LDADD.
+
+	* waveproducer.cc: Renamed from wavegenerator.cc
+
+2007-11-01  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am (bin_PROGRAMS): Added launchtest.
+
+	* launchest.cc, launchtest.music: New files.
+
+	* wavegenerator.cc (main): Don't pass color to setup.
+
+	* waveconsumer.cc (main): Don't pass color to setup.
+
+	* application1.cc (main): Don't pass color to setup.
+
+2007-10-19  Örjan Ekeberg  <orjan@nada.kth.se>
+
+	* wavegenerator.cc, waveconsumer.cc, application1.cc: Replace C
+	MPI calls with their C++ equivalents.
+
+2007-10-19  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* wavegenerator.cc (main): Renamed array_data, linear_index from
+	arraydata, linearindex.
+
+2007-10-18  Örjan Ekeberg  <orjan@nada.kth.se>
+
+	* wavegenerator.cc: Added new miniature application.
+
+	* Makefile.am: Added rule to build wavegenerator.
+
+2007-09-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* application1.cc: Modified to conform to setup.hh and runtime.hh.
+
+	* Makefile.am: New file.
+
+2007-08-17  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Pling!
+
diff --git a/testsuite/test_old/chain.music b/testsuite/test_old/chain.music
new file mode 100644
index 0000000..8530473
--- /dev/null
+++ b/testsuite/test_old/chain.music
@@ -0,0 +1,15 @@
+np=1
+stoptime=1.0
+[from]
+  np=2
+  binary=./eventsource
+  args=-b 2 10 spikes
+[mid]
+  binary=./eventdelay
+  args=-d 0.3
+[to]
+  binary=./eventlogger
+  args=-b 2
+
+from.out -> mid.in [10, collective]
+mid.out -> to.in [10]
diff --git a/testsuite/test_old/cloop.music b/testsuite/test_old/cloop.music
new file mode 100644
index 0000000..64e5fad
--- /dev/null
+++ b/testsuite/test_old/cloop.music
@@ -0,0 +1,19 @@
+np=1
+stoptime=1.0
+[A]
+  binary=./contdelay
+  args=-d 0.1 -b 1000
+[B]
+  binary=./contdelay
+  args=-d 0.1 -b 1000
+[from]
+  binary=./clocksource
+  args=-b 5
+[to]
+  binary=./contsink
+
+
+from.clock -> A.in [1]
+A.out -> B.in [1]
+B.out -> to.contdata [1]
+B.out -> A.aux [1]
diff --git a/testsuite/test_old/coba.cc b/testsuite/test_old/coba.cc
new file mode 100644
index 0000000..cc054dd
--- /dev/null
+++ b/testsuite/test_old/coba.cc
@@ -0,0 +1,350 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007 CSC, KTH
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define N 4000
+
+#define T 5.0
+#define DT 1e-4
+#define PRINT_EVERY_NTH 100
+#define N_PLOTTED_ECELLS 5
+#define N_PLOTTED_ICELLS 5
+
+#define cell_area 20000e-12
+#define tau_m        20e-3
+#define C_m           1e-2
+#define rho_leak      5e-1
+#define Erev_leak   -65e-3
+
+#define Gexc	      6e-9
+#define Ginh	     67e-9
+#define Erev_exc      0
+#define Erev_inh    -80e-3
+#define tau_exc       5e-3
+#define tau_inh      10e-3
+
+#define conn_prob     0.02
+#define conn_delay    1e-6 // arbitrary non-zero
+
+#define gNa	     0.1e4
+#define gKd	    0.03e4
+#define ENa	     50e-3
+#define EK	    -90e-3
+#define Vtr	    -63e-3
+
+#define N_e ((int) (0.8 * N))
+#define N_i (N - N_e)
+
+#include <iostream>
+#include <cmath>
+
+#include <split.hh>
+#include <split/connection-set.hh>
+
+using namespace libsplit;
+
+class projection;
+
+class cells
+{
+private:
+  split_int* split;
+  int _pop_id;
+  int _leak_id;
+  int _na_id;
+  int _k_id;
+  int _size;
+
+public:
+  cells (split_int* _split, int size);
+  int pop_id () { return _pop_id; }
+  int na_id () { return _na_id; }
+  int size () { return _size; }
+  
+  projection* project (cells* post);
+  
+  void set_parameters ();
+};
+
+class projection
+{
+  split_int* split;
+  int proj_id;
+  connection_set c;
+public:
+  projection (split_int* _split, cells& pre, cells& post)
+    : split (_split), c (random_uniform (conn_prob))
+  {
+    c.init (0, pre.size (), 0, post.size ());
+    proj_id = split->create_projection (CHEMICAL_SYNAPSE, SCALAR,
+					pre.pop_id (), CONTRIB, pre.na_id (),
+					post.pop_id (), 0,
+					c.size ());
+    for (c.begin (); !c.end (); ++c)
+      {
+	split->set_projection_index_int (proj_id, SYN_PRE, c.id (), c.pre ());
+	split->set_projection_index_int (proj_id, SYN_POST, c.id (), c.post ());
+	split->set_projection_index_real (proj_id, SYN_DELAY, c.id (),
+					  conn_delay);
+      }
+  }
+  
+  void set_parameters (double G, double Erev, double tau)
+  {
+    split->set_projection_scalar_real (proj_id, SYN_E, Erev);
+    split->set_projection_scalar_real (proj_id, SYN_DURATION, 0.0);
+    split->set_projection_scalar_real (proj_id, SYN_RAISE, 0.0);
+    split->set_projection_scalar_real (proj_id, SYN_DECAY, tau);
+    for (c.begin (); !c.end (); ++c)
+      split->set_projection_index_real (proj_id, SYN_G, c.id (), G);
+  }
+};
+
+cells::cells (split_int* _split, int size)
+  : split (_split), _size (size)
+{
+  int tree_map[1] = { 0 };
+  _pop_id = split->create_population ();
+  split->create_electric_tree (_pop_id, ELECTRIC_SCALAR_STAR, N_e, 0, 0,
+			       tree_map /* dummy */ );
+  _leak_id = split->create_e_leak (_pop_id, N_e, 0);
+  _na_id = split->create_simple_channel (_pop_id, TRAUB_NA, SCALAR, N_e, 0);
+  _k_id = split->create_simple_channel (_pop_id, HH_K, SCALAR, N_e, 0);
+}
+
+projection*
+cells::project (cells* post)
+{
+  return new projection (split, *this, *post);
+}
+  
+void
+cells::set_parameters ()
+{
+  split->set_scalar_real (_pop_id, ELECTRIC, 0, CM, cell_area * C_m);
+  split->set_scalar_real (_pop_id, ELECTRIC, 0, GCORE, 0);
+  split->set_scalar_real (_pop_id, CONTRIB, _leak_id, E_LEAK_E, Erev_leak);
+  for (int i = 0; i < _size; ++i)
+    {
+      split->set_index_real (_pop_id, ELECTRIC, 0, INITIAL, i, Erev_leak);
+      split->set_index_real (_pop_id, CONTRIB, _leak_id,
+			     E_LEAK_G_M, i, cell_area * rho_leak);
+    }
+
+  // Na activation
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  ACT_ALPHA_A, 0.32e6);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  ACT_ALPHA_B, 13e-3 + Vtr);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  ACT_ALPHA_C, 4e-3);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  ACT_BETA_A, 0.28e6);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  ACT_BETA_B, 40e-3 + Vtr);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  ACT_BETA_C, 5e-3);
+  split->set_scalar_int (_pop_id, CONTRIB, _na_id,
+			 ACT_EXPO, 3);
+  // Na inactivation
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  INACT_ALPHA_A, 0.128e3);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  INACT_ALPHA_B, 17e-3 + Vtr);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  INACT_ALPHA_C, 18e-3);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  INACT_BETA_A, 4e3);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  INACT_BETA_B, 40e-3 + Vtr);
+  split->set_scalar_real (_pop_id, CONTRIB, _na_id,
+			  INACT_BETA_C, 5e-3);
+  split->set_scalar_int (_pop_id, CONTRIB, _na_id,
+			 INACT_EXPO, 1);
+  // K
+  split->set_scalar_real (_pop_id, CONTRIB, _k_id,
+			  ACT_ALPHA_A, 0.032e6);
+  split->set_scalar_real (_pop_id, CONTRIB, _k_id,
+			  ACT_ALPHA_B, 15e-3 + Vtr);
+  split->set_scalar_real (_pop_id, CONTRIB, _k_id,
+			  ACT_ALPHA_C, 5e-3);
+  split->set_scalar_real (_pop_id, CONTRIB, _k_id,
+			  ACT_BETA_A, 0.5e3);
+  split->set_scalar_real (_pop_id, CONTRIB, _k_id,
+			  ACT_BETA_B, 10e-3 + Vtr);
+  split->set_scalar_real (_pop_id, CONTRIB, _k_id,
+			  ACT_BETA_C, 40e-3);
+  split->set_scalar_int (_pop_id, CONTRIB, _k_id,
+			 ACT_EXPO, 4);
+
+  for (int i = 0; i < _size; ++i)
+    {
+      // Na
+      split->set_index_real (_pop_id, CONTRIB, _na_id,
+			     CHAN_E, i, ENa);
+      split->set_index_real (_pop_id, CONTRIB, _na_id,
+			     CHAN_G, i, cell_area * gNa);
+      // K
+      split->set_index_real (_pop_id, CONTRIB, _k_id,
+			     CHAN_E, i, EK);
+      split->set_index_real (_pop_id, CONTRIB, _k_id,
+			     CHAN_G, i, cell_area * gKd);
+    }
+}
+
+class noise {
+  split_int* split;
+  cells* c;
+  int id;
+public:
+  noise (split_int*  _split, cells* _c)
+    : split (_split), c (_c)
+  {
+    id = split->create_noise (c->pop_id (), c->size (), 0);
+  }
+  void set_parameters ()
+  {
+    for (int i = 0; i < c->size (); ++i)
+      {
+	split->set_index_real (c->pop_id (), CONTRIB, id,
+			       NOISE_E, i, 0);
+	split->set_index_real (c->pop_id (), CONTRIB, id,
+			       NOISE_G, i, 7.5e-10);
+	split->set_index_real (c->pop_id (), CONTRIB, id,
+			       NOISE_INTENSITY, i, 100);
+	split->set_index_real (c->pop_id (), CONTRIB, id,
+			       NOISE_INITIAL, i, 0);
+	split->set_index_real (c->pop_id (), CONTRIB, id,
+			       NOISE_TAU, i, 0.01);
+	split->set_index_real (c->pop_id (), CONTRIB, id,
+			       NOISE_START_TIME, i, 0);
+	split->set_index_real (c->pop_id (), CONTRIB, id,
+			       NOISE_END_TIME, i, 0.05);
+      }
+  }
+};
+
+void
+setup_volts_plot (split_int* split, int id, cells* c, int n, int& idx)
+{
+  for (int i = 0; i < n; ++i)
+    {
+      split->set_plot_index_int (id, idx, PLOT_ID, 0);
+      split->set_plot_index_int (id, idx, PLOT_POP_ID, c->pop_id ());
+      split->set_plot_index_int (id, idx, PLOT_TYPE, ELECTRIC);
+      split->set_plot_index_int (id, idx, PLOT_TAG, STATE_SV);
+      split->set_plot_index_int (id, idx, PLOT_IDX, i);
+      split->set_plot_index_real (id, idx, PLOT_MIN, -0.08);
+      split->set_plot_index_real (id, idx, PLOT_MAX, 0.05);
+      ++idx;
+    }
+}
+
+int
+main (int argc, char **argv)
+{
+  std::cout << "Setup\n";
+  
+  split_int* split = new split_int (&argc, &argv);
+  
+  // Create cells
+  cells* ecells = new cells (split, N_e);
+  cells* icells = new cells (split, N_i);
+  
+  // Create synapses
+  projection* ee = ecells->project (ecells);
+  projection* ei = ecells->project (icells);
+  projection* ii = icells->project (icells);
+  projection* ie = icells->project (ecells);
+
+  // Create ports
+  int n_ports = 0;
+  while (true)
+    {
+      std::ostrstream portname;
+      portname << "ein" << n_ports;
+      if (is_port (portname.str ()))
+	{
+	  split->create_spike_input (portname.str (), ecells->pop_id (), 0, N);
+	  std::ostrstream portname;
+	  portname << "iin" << n_ports;
+	  if (is_port (portname.sr ()))
+	    split->create_spike_input (portname.str (), icells->pop_id (), 0, N);
+	  ++n_ports;
+	}
+      else
+	break;
+    }
+  if (n_ports > 0)
+    {
+      split->create_spike_output ("eout", ecells->pop_id (), CONTRIB, ecells->na_id ());
+      split->create_spike_output ("iout", icells->pop_id (), CONTRIB, icells->na_id ());
+    }
+  
+  // Noiseinjection
+  noise* enoise = new noise (split, ecells);
+  noise* inoise = new noise (split, icells);
+  
+  // Volt plots
+  int volts_id = split->create_plot ("volts.out",
+				     N_PLOTTED_ECELLS + N_PLOTTED_ICELLS);
+  split->set_plot_scalar_int (volts_id, PLOT_EVERY_NTH, 1);
+  int idx = 0;
+  setup_volts_plot (split, volts_id, ecells, N_PLOTTED_ECELLS, idx);
+  setup_volts_plot (split, volts_id, icells, N_PLOTTED_ICELLS, idx);
+  
+  // Spike plot
+  int spikes_id = split->create_spike_plot_ranges ("spikes.out");
+  split->set_plot_range (spikes_id, ecells->pop_id (), ELECTRIC, 0,
+			 STATE_SV, 0, ecells->size ());
+  split->set_plot_range (spikes_id, icells->pop_id (), ELECTRIC, 0,
+			 STATE_SV, 0, icells->size ());
+  
+  // Distribute simulation onto slaves
+  split->map (0);
+  
+  // Cell parameters
+  ecells->set_parameters ();
+  icells->set_parameters ();
+  
+  // Synaptic parameters
+  ee->set_parameters (Gexc, Erev_exc, tau_exc);
+  ei->set_parameters (Gexc, Erev_exc, tau_exc);
+  ii->set_parameters (Ginh, Erev_inh, tau_inh);
+  ie->set_parameters (Ginh, Erev_inh, tau_inh);
+
+  // Noise parameters
+  enoise->set_parameters ();
+  inoise->set_parameters ();
+  
+  // Allocate
+  split->allocate (0.0, T, DT);
+  
+  // Initialize
+  split->initialize (DT);
+  
+  // Simulate
+  std::cout << "Simulate\n";
+  int total_steps = (int) ceil (T / DT);
+  for (int steps = 0; steps < total_steps; steps += PRINT_EVERY_NTH)
+    split->simulate (PRINT_EVERY_NTH);
+  
+  // Quit
+  split->quit ();
+  
+  return 0;
+}
diff --git a/testsuite/test_old/const.music b/testsuite/test_old/const.music
new file mode 100644
index 0000000..59a3fe2
--- /dev/null
+++ b/testsuite/test_old/const.music
@@ -0,0 +1,8 @@
+stoptime=1.0
+[from]
+  np=2
+  binary=./constsource
+[to]
+  np=2
+  binary=./contsink
+  from.contdata -> to.contdata [7,collective]
diff --git a/testsuite/test_old/contclock.music b/testsuite/test_old/contclock.music
new file mode 100644
index 0000000..1114f36
--- /dev/null
+++ b/testsuite/test_old/contclock.music
@@ -0,0 +1,10 @@
+stoptime=0.5
+[from]
+  np=1
+  binary=./clocksource
+  args=-t 0.02 -b 3
+[to]
+  np=1
+  binary=./contsink
+  args=-t 0.03
+  from.clock -> to.contdata [1]
diff --git a/testsuite/test_old/divergence.music b/testsuite/test_old/divergence.music
new file mode 100644
index 0000000..531b9ff
--- /dev/null
+++ b/testsuite/test_old/divergence.music
@@ -0,0 +1,10 @@
+stoptime=1.0
+[from]
+  binary=./eventsource
+  args=10 spikes
+  np=1
+[to]
+  binary=./eventlogger
+  args=-a
+  np=2
+  from.out -> to.in [10, collective]
diff --git a/testsuite/test_old/events.music b/testsuite/test_old/events.music
new file mode 100644
index 0000000..77fbffb
--- /dev/null
+++ b/testsuite/test_old/events.music
@@ -0,0 +1,9 @@
+np=2
+stoptime=1.0
+[from]
+  binary=./eventsource
+  args=-b 1 10 spikes
+[to]
+  binary=./eventlogger
+  args=-b 2
+  from.out -> to.in [10]
diff --git a/testsuite/test_old/events.py b/testsuite/test_old/events.py
new file mode 100644
index 0000000..f895e11
--- /dev/null
+++ b/testsuite/test_old/events.py
@@ -0,0 +1,12 @@
+import os
+
+from music import *
+
+define ('stoptime', 1.0)
+
+app1 = Application (2, 'eventsource', '-b 1 10 spikes')
+app2 = Application (2, 'eventlogger', '-b 2')
+
+connect (app1, 'out', app2, 'in', 10)
+
+launch ()
diff --git a/testsuite/test_old/fork.music b/testsuite/test_old/fork.music
new file mode 100644
index 0000000..e040d04
--- /dev/null
+++ b/testsuite/test_old/fork.music
@@ -0,0 +1,11 @@
+np=2
+stoptime=1.0
+[from]
+  binary=./eventsource
+  args=10 spikes
+[to]
+  binary=./eventlogger
+  from.out -> to.in [10]
+[two]
+  binary=./eventlogger
+  from.out -> two.in [10]
diff --git a/testsuite/test_old/launcher.cc b/testsuite/test_old/launcher.cc
new file mode 100644
index 0000000..5b5f9ab
--- /dev/null
+++ b/testsuite/test_old/launcher.cc
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <rts.h>
+
+
+extern char **environ;
+
+
+int main(int nargs, char **argv) {
+  int err;
+
+  BGLPersonality whoAmI;
+
+  rts_get_personality(&whoAmI, sizeof whoAmI);
+
+  if(whoAmI.zCoord < whoAmI.zSize / 2) {
+    printf("%d starts as first\n", whoAmI.zCoord);
+    err = execve("/gpfs/scratch/o/orjan/application1", argv, environ);
+  } else {
+    printf("%d starts as second\n", whoAmI.zCoord);
+    err = execve("/gpfs/scratch/o/orjan/application2", argv, environ);
+  }
+
+  //Should not get here....
+  printf("Note: execve call returned %d\n", err);
+  return(-1);
+}
diff --git a/testsuite/test_old/launchtest.music b/testsuite/test_old/launchtest.music
new file mode 100644
index 0000000..d752ab1
--- /dev/null
+++ b/testsuite/test_old/launchtest.music
@@ -0,0 +1,13 @@
+binary=./launchtest
+np=3
+[1]
+  args=hej du glade
+  param=1.0
+[2]
+  args=ta en spade
+  param=2.0
+  1.as1 -> 2.bd1
+  2.bd2 <- 1.as2 # asd
+  bd2 -> 2.as2 [12]
+
+
diff --git a/testsuite/test_old/loop.music b/testsuite/test_old/loop.music
new file mode 100644
index 0000000..7c5ff6f
--- /dev/null
+++ b/testsuite/test_old/loop.music
@@ -0,0 +1,20 @@
+np=1
+stoptime=1.1
+[A]
+  binary=./eventdelay
+  args=-d 0.1 -L 1 -b 2
+[B]
+  binary=./eventdelay
+  args=-d 0.1 -L 2 -b 2
+[from]
+  binary=./eventsource
+  args=-b 5 10 spikes
+[to]
+  binary=./eventlogger
+  args=-b 5
+
+
+from.out -> A.in [10]
+A.out -> B.in [10]
+B.out -> A.aux [10]
+B.out -> to.in [10]
diff --git a/testsuite/test_old/multicomm.music b/testsuite/test_old/multicomm.music
new file mode 100644
index 0000000..b4cc627
--- /dev/null
+++ b/testsuite/test_old/multicomm.music
@@ -0,0 +1,16 @@
+stoptime=1.0
+np=2
+[S0]
+  binary=eventsource
+  args=--out out0 10 spikes
+[S1]
+  binary=eventsource
+  args=--out out1 10 spikes
+[R0]
+  binary=eventlogger
+  args=--in in0
+[R1]
+  binary=eventlogger
+  args=--in in1
+S0.out0 -> R0.in0 [10]
+S1.out1 -> R1.in1 [10]
diff --git a/testsuite/test_old/multipoisson.music b/testsuite/test_old/multipoisson.music
new file mode 100644
index 0000000..b021b7b
--- /dev/null
+++ b/testsuite/test_old/multipoisson.music
@@ -0,0 +1,19 @@
+stoptime=10.0
+[mid]
+  np=1
+  binary=eventdelay
+  args=-d 0.1 -b 2
+[from]
+  np=1
+  binary=eventgenerator
+  args=-b 2 12
+[to]
+  np=1
+  binary=eventsink
+  args=12 multipoisson .dat
+#  binary=eventlogger
+#  args=-b 2
+#  from.out -> mid.in [12]
+#  mid.out -> to.in [12]
+  from.out -> mid.in [12,collective]
+  mid.out -> to.in [12,collective]
diff --git a/testsuite/test_old/multipoisson2.music b/testsuite/test_old/multipoisson2.music
new file mode 100644
index 0000000..b021b7b
--- /dev/null
+++ b/testsuite/test_old/multipoisson2.music
@@ -0,0 +1,19 @@
+stoptime=10.0
+[mid]
+  np=1
+  binary=eventdelay
+  args=-d 0.1 -b 2
+[from]
+  np=1
+  binary=eventgenerator
+  args=-b 2 12
+[to]
+  np=1
+  binary=eventsink
+  args=12 multipoisson .dat
+#  binary=eventlogger
+#  args=-b 2
+#  from.out -> mid.in [12]
+#  mid.out -> to.in [12]
+  from.out -> mid.in [12,collective]
+  mid.out -> to.in [12,collective]
diff --git a/testsuite/test_old/multiport.music b/testsuite/test_old/multiport.music
new file mode 100644
index 0000000..580fc62
--- /dev/null
+++ b/testsuite/test_old/multiport.music
@@ -0,0 +1,21 @@
+stoptime=1.0
+[A]
+  binary=multiport
+  args=--in in0:2640 --in in1:2640 --in in2:1 --out out0:968 --out out1:968 --out out2:1 --out out3:1
+  np=2
+[B]
+  binary=multiport
+  args=--in in0:1 --out out0:2640 --out out1:2640 --out out2:1
+  np=1
+[C]
+  binary=multiport
+  args=--in in0:968 --in in1:968 --in in2:1 --in in3:1 --out out0:1
+  np=1
+B.out0 -> A.in0 [2640,collective]
+B.out1 -> A.in1 [2640,collective]
+B.out2 -> A.in2 [1,collective]
+A.out0 -> C.in0 [968,collective]
+A.out1 -> C.in1 [968,collective]
+A.out2 -> C.in2 [1,collective]
+A.out3 -> C.in3 [1,collective]
+C.out0 -> B.in0 [1,collective]
diff --git a/testsuite/test_old/parsetest.cc b/testsuite/test_old/parsetest.cc
new file mode 100644
index 0000000..3f637a5
--- /dev/null
+++ b/testsuite/test_old/parsetest.cc
@@ -0,0 +1,48 @@
+// Länkas ståendes i katalogin music/utils:
+//
+// g++ -o parsetest -I .. parsetest.cc -L ../rudeconfig/.libs -l rudeconfig 
+//
+// Användning:
+// Behvovs inte,... typ
+// export LD_LIBRARY_PATH=/home/hjorth/music/rudeconfig/.libs
+//
+// LD_LIBRARY_PATH=/home/hjorth/music/rudeconfig/.libs ./parsetest ../test/launchtest.music
+
+#include "rudeconfig/src/config.h"
+#include <iostream>
+
+int
+main (int argc, char** argv)
+{
+  rude::Config* cfile = new rude::Config ();
+  cfile->load (argv[1]);
+  int n_sections = cfile->getNumSections ();
+  for (int s = 0; s < n_sections; ++s)
+    {
+      const char* name = cfile->getSectionNameAt (s);
+      cfile->setSection (name);
+      std::cout << "Section \"" << name << "\":" << std::endl;
+
+      int n_members = cfile->getNumDataMembers ();
+      for (int m = 0; m < n_members; ++m)
+	{
+	  const char* name = cfile->getDataNameAt (m);
+	  std::cout << name << '\t' << cfile->getStringValue (name) << std::endl;
+	}
+
+      int n_sd = cfile->getNumSourceDestMembers();
+
+      for (int i = 0; i < n_sd; i++)
+        {
+          const char* srcApp = cfile->getSrcAppAt(i);
+          const char* srcObj = cfile->getSrcObjAt(i);
+          const char* destApp = cfile->getDestAppAt(i);
+          const char* destObj = cfile->getDestObjAt(i);
+          const char* width = cfile->getWidthAt(i);
+
+          std::cout << srcApp << "." << srcObj 
+                    << " -> " << destApp << "." << destObj
+                    << " [" << width << "]\n";
+        }
+    }
+}
diff --git a/testsuite/test_old/poisson.music b/testsuite/test_old/poisson.music
new file mode 100644
index 0000000..ecdc44b
--- /dev/null
+++ b/testsuite/test_old/poisson.music
@@ -0,0 +1,10 @@
+stoptime=10.0
+[from]
+  np=4
+  binary=eventgenerator
+  args=-b 2 16
+[to]
+  np=4
+  binary=eventsink
+  args=16 poisson .dat
+  from.out -> to.in [16,collective]
diff --git a/testsuite/test_old/poisson2.music b/testsuite/test_old/poisson2.music
new file mode 100644
index 0000000..dc7b5dd
--- /dev/null
+++ b/testsuite/test_old/poisson2.music
@@ -0,0 +1,9 @@
+np=1
+stoptime=10.0
+[from]
+  binary=eventgenerator
+  args=-b 2 16
+[to]
+  binary=eventsink
+  args=16 poisson .dat
+  from.out -> to.in [16,collective]
diff --git a/testsuite/unittests/catch/.gitignore b/testsuite/unittests/catch/.gitignore
new file mode 100644
index 0000000..89e8275
--- /dev/null
+++ b/testsuite/unittests/catch/.gitignore
@@ -0,0 +1 @@
+test_ag
diff --git a/testsuite/unittests/catch/Makefile.am b/testsuite/unittests/catch/Makefile.am
new file mode 100644
index 0000000..ecc1316
--- /dev/null
+++ b/testsuite/unittests/catch/Makefile.am
@@ -0,0 +1,19 @@
+## Process this file with Automake to create Makefile.in
+
+ACLOCAL = $(top_srcdir)/aclocal.sh
+
+testlibdir =  $(libdir)/@PACKAGE@-@PACKAGE_VERSION@
+testlib_PROGRAMS =  test_ag #test_tng 
+
+MUSIC_INCLUDE = -I$(top_srcdir)/src -I$(top_builddir)/src
+
+test_ag_SOURCES = test_ag.cc
+test_ag_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+test_ag_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+#test_tng_SOURCES = tc_temporal_negotiator_graph.cc
+#test_tng_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+#test_tng_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+
+MKDEP = gcc -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
diff --git a/testsuite/unittests/catch/catch.hpp b/testsuite/unittests/catch/catch.hpp
new file mode 100644
index 0000000..03665c4
--- /dev/null
+++ b/testsuite/unittests/catch/catch.hpp
@@ -0,0 +1,8891 @@
+/*
+ *  CATCH v1.0 build 43 (master branch)
+ *  Generated: 2014-05-04 09:22:51.466832
+ *  ----------------------------------------------------------
+ *  This file has been merged from multiple headers. Please don't edit it directly
+ *  Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
+ *
+ *  Distributed under the Boost Software License, Version 1.0. (See accompanying
+ *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
+#define TWOBLUECUBES_CATCH_HPP_INCLUDED
+
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wglobal-constructors"
+#pragma clang diagnostic ignored "-Wvariadic-macros"
+#pragma clang diagnostic ignored "-Wc99-extensions"
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#pragma clang diagnostic ignored "-Wc++98-compat"
+#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#endif
+
+#ifdef CATCH_CONFIG_MAIN
+#  define CATCH_CONFIG_RUNNER
+#endif
+
+#ifdef CATCH_CONFIG_RUNNER
+#  ifndef CLARA_CONFIG_MAIN
+#    define CLARA_CONFIG_MAIN_NOT_DEFINED
+#    define CLARA_CONFIG_MAIN
+#  endif
+#endif
+
+// #included from: internal/catch_notimplemented_exception.h
+#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
+
+// #included from: catch_common.h
+#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
+
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
+#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
+
+#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
+#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
+
+#include <sstream>
+#include <stdexcept>
+#include <algorithm>
+
+// #included from: catch_compiler_capabilities.h
+#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
+
+// Much of the following code is based on Boost (1.53)
+
+#ifdef __clang__
+
+#  if __has_feature(cxx_nullptr)
+#    define CATCH_CONFIG_CPP11_NULLPTR
+#  endif
+
+#  if __has_feature(cxx_noexcept)
+#    define CATCH_CONFIG_CPP11_NOEXCEPT
+#  endif
+
+#endif // __clang__
+
+////////////////////////////////////////////////////////////////////////////////
+// Borland
+#ifdef __BORLANDC__
+
+#if (__BORLANDC__ > 0x582 )
+//#define CATCH_CONFIG_SFINAE // Not confirmed
+#endif
+
+#endif // __BORLANDC__
+
+////////////////////////////////////////////////////////////////////////////////
+// EDG
+#ifdef __EDG_VERSION__
+
+#if (__EDG_VERSION__ > 238 )
+//#define CATCH_CONFIG_SFINAE // Not confirmed
+#endif
+
+#endif // __EDG_VERSION__
+
+////////////////////////////////////////////////////////////////////////////////
+// Digital Mars
+#ifdef __DMC__
+
+#if (__DMC__ > 0x840 )
+//#define CATCH_CONFIG_SFINAE // Not confirmed
+#endif
+
+#endif // __DMC__
+
+////////////////////////////////////////////////////////////////////////////////
+// GCC
+#ifdef __GNUC__
+
+#if __GNUC__ < 3
+
+#if (__GNUC_MINOR__ >= 96 )
+//#define CATCH_CONFIG_SFINAE
+#endif
+
+#elif __GNUC__ >= 3
+
+// #define CATCH_CONFIG_SFINAE // Taking this out completely for now
+
+#endif // __GNUC__ < 3
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
+
+#define CATCH_CONFIG_CPP11_NULLPTR
+#endif
+
+#endif // __GNUC__
+
+////////////////////////////////////////////////////////////////////////////////
+// Visual C++
+#ifdef _MSC_VER
+
+#if (_MSC_VER >= 1310 ) // (VC++ 7.0+)
+//#define CATCH_CONFIG_SFINAE // Not confirmed
+#endif
+
+#endif // _MSC_VER
+
+// Use variadic macros if the compiler supports them
+#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
+    ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
+    ( defined __GNUC__ && __GNUC__ >= 3 ) || \
+    ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
+
+#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS
+#define CATCH_CONFIG_VARIADIC_MACROS
+#endif
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// C++ language feature support
+
+// detect language version:
+#if (__cplusplus == 201103L)
+#  define CATCH_CPP11
+#  define CATCH_CPP11_OR_GREATER
+#elif (__cplusplus >= 201103L)
+#  define CATCH_CPP11_OR_GREATER
+#endif
+
+// noexcept support:
+#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
+#  define CATCH_NOEXCEPT noexcept
+#  define CATCH_NOEXCEPT_IS(x) noexcept(x)
+#else
+#  define CATCH_NOEXCEPT throw()
+#  define CATCH_NOEXCEPT_IS(x)
+#endif
+
+namespace Catch {
+
+    class NonCopyable {
+        NonCopyable( NonCopyable const& );
+        void operator = ( NonCopyable const& );
+    protected:
+        NonCopyable() {}
+        virtual ~NonCopyable();
+    };
+
+    class SafeBool {
+    public:
+        typedef void (SafeBool::*type)() const;
+
+        static type makeSafe( bool value ) {
+            return value ? &SafeBool::trueValue : 0;
+        }
+    private:
+        void trueValue() const {}
+    };
+
+    template<typename ContainerT>
+    inline void deleteAll( ContainerT& container ) {
+        typename ContainerT::const_iterator it = container.begin();
+        typename ContainerT::const_iterator itEnd = container.end();
+        for(; it != itEnd; ++it )
+            delete *it;
+    }
+    template<typename AssociativeContainerT>
+    inline void deleteAllValues( AssociativeContainerT& container ) {
+        typename AssociativeContainerT::const_iterator it = container.begin();
+        typename AssociativeContainerT::const_iterator itEnd = container.end();
+        for(; it != itEnd; ++it )
+            delete it->second;
+    }
+
+    bool startsWith( std::string const& s, std::string const& prefix );
+    bool endsWith( std::string const& s, std::string const& suffix );
+    bool contains( std::string const& s, std::string const& infix );
+    void toLowerInPlace( std::string& s );
+    std::string toLower( std::string const& s );
+    std::string trim( std::string const& str );
+
+    struct pluralise {
+        pluralise( std::size_t count, std::string const& label );
+
+        friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
+
+        std::size_t m_count;
+        std::string m_label;
+    };
+
+    struct SourceLineInfo {
+
+        SourceLineInfo();
+        SourceLineInfo( char const* _file, std::size_t _line );
+        SourceLineInfo( SourceLineInfo const& other );
+#  ifdef CATCH_CPP11_OR_GREATER
+        SourceLineInfo( SourceLineInfo && )                  = default;
+        SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
+        SourceLineInfo& operator = ( SourceLineInfo && )     = default;
+#  endif
+        bool empty() const;
+        bool operator == ( SourceLineInfo const& other ) const;
+
+        std::string file;
+        std::size_t line;
+    };
+
+    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
+
+    // This is just here to avoid compiler warnings with macro constants and boolean literals
+    inline bool isTrue( bool value ){ return value; }
+
+    void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
+
+    // Use this in variadic streaming macros to allow
+    //    >> +StreamEndStop
+    // as well as
+    //    >> stuff +StreamEndStop
+    struct StreamEndStop {
+        std::string operator+() {
+            return std::string();
+        }
+    };
+    template<typename T>
+    T const& operator + ( T const& value, StreamEndStop ) {
+        return value;
+    }
+}
+
+#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
+#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
+
+#include <ostream>
+
+namespace Catch {
+
+    class NotImplementedException : public std::exception
+    {
+    public:
+        NotImplementedException( SourceLineInfo const& lineInfo );
+
+        virtual ~NotImplementedException() CATCH_NOEXCEPT {}
+
+        virtual const char* what() const CATCH_NOEXCEPT;
+
+    private:
+        std::string m_what;
+        SourceLineInfo m_lineInfo;
+    };
+
+} // end namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
+
+// #included from: internal/catch_context.h
+#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
+
+// #included from: catch_interfaces_generators.h
+#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    struct IGeneratorInfo {
+        virtual ~IGeneratorInfo();
+        virtual bool moveNext() = 0;
+        virtual std::size_t getCurrentIndex() const = 0;
+    };
+
+    struct IGeneratorsForTest {
+        virtual ~IGeneratorsForTest();
+
+        virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
+        virtual bool moveNext() = 0;
+    };
+
+    IGeneratorsForTest* createGeneratorsForTest();
+
+} // end namespace Catch
+
+// #included from: catch_ptr.hpp
+#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+    // An intrusive reference counting smart pointer.
+    // T must implement addRef() and release() methods
+    // typically implementing the IShared interface
+    template<typename T>
+    class Ptr {
+    public:
+        Ptr() : m_p( NULL ){}
+        Ptr( T* p ) : m_p( p ){
+            if( m_p )
+                m_p->addRef();
+        }
+        Ptr( Ptr const& other ) : m_p( other.m_p ){
+            if( m_p )
+                m_p->addRef();
+        }
+        ~Ptr(){
+            if( m_p )
+                m_p->release();
+        }
+        void reset() {
+            if( m_p )
+                m_p->release();
+            m_p = NULL;
+        }
+        Ptr& operator = ( T* p ){
+            Ptr temp( p );
+            swap( temp );
+            return *this;
+        }
+        Ptr& operator = ( Ptr const& other ){
+            Ptr temp( other );
+            swap( temp );
+            return *this;
+        }
+        void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
+        T* get() { return m_p; }
+        const T* get() const{ return m_p; }
+        T& operator*() const { return *m_p; }
+        T* operator->() const { return m_p; }
+        bool operator !() const { return m_p == NULL; }
+        operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
+
+    private:
+        T* m_p;
+    };
+
+    struct IShared : NonCopyable {
+        virtual ~IShared();
+        virtual void addRef() const = 0;
+        virtual void release() const = 0;
+    };
+
+    template<typename T = IShared>
+    struct SharedImpl : T {
+
+        SharedImpl() : m_rc( 0 ){}
+
+        virtual void addRef() const {
+            ++m_rc;
+        }
+        virtual void release() const {
+            if( --m_rc == 0 )
+                delete this;
+        }
+
+        mutable unsigned int m_rc;
+    };
+
+} // end namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#include <memory>
+#include <vector>
+#include <stdlib.h>
+
+namespace Catch {
+
+    class TestCase;
+    class Stream;
+    struct IResultCapture;
+    struct IRunner;
+    struct IGeneratorsForTest;
+    struct IConfig;
+
+    struct IContext
+    {
+        virtual ~IContext();
+
+        virtual IResultCapture& getResultCapture() = 0;
+        virtual IRunner& getRunner() = 0;
+        virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
+        virtual bool advanceGeneratorsForCurrentTest() = 0;
+        virtual Ptr<IConfig const> getConfig() const = 0;
+    };
+
+    struct IMutableContext : IContext
+    {
+        virtual ~IMutableContext();
+        virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
+        virtual void setRunner( IRunner* runner ) = 0;
+        virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
+    };
+
+    IContext& getCurrentContext();
+    IMutableContext& getCurrentMutableContext();
+    void cleanUpContext();
+    Stream createStream( std::string const& streamName );
+
+}
+
+// #included from: internal/catch_test_registry.hpp
+#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
+
+// #included from: catch_interfaces_testcase.h
+#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
+
+#include <vector>
+
+namespace Catch {
+
+    class TestCaseFilters;
+
+    struct ITestCase : IShared {
+        virtual void invoke () const = 0;
+    protected:
+        virtual ~ITestCase();
+    };
+
+    class TestCase;
+    struct IConfig;
+
+    struct ITestCaseRegistry {
+        virtual ~ITestCaseRegistry();
+        virtual std::vector<TestCase> const& getAllTests() const = 0;
+        virtual void getFilteredTests( TestCaseFilters const& filters, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0;
+        virtual void getFilteredTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0;
+
+    };
+}
+
+namespace Catch {
+
+template<typename C>
+class MethodTestCase : public SharedImpl<ITestCase> {
+
+public:
+    MethodTestCase( void (C::*method)() ) : m_method( method ) {}
+
+    virtual void invoke() const {
+        C obj;
+        (obj.*m_method)();
+    }
+
+private:
+    virtual ~MethodTestCase() {}
+
+    void (C::*m_method)();
+};
+
+typedef void(*TestFunction)();
+
+struct NameAndDesc {
+    NameAndDesc( const char* _name = "", const char* _description= "" )
+    : name( _name ), description( _description )
+    {}
+
+    const char* name;
+    const char* description;
+};
+
+struct AutoReg {
+
+    AutoReg(    TestFunction function,
+                SourceLineInfo const& lineInfo,
+                NameAndDesc const& nameAndDesc );
+
+    template<typename C>
+    AutoReg(    void (C::*method)(),
+                char const* className,
+                NameAndDesc const& nameAndDesc,
+                SourceLineInfo const& lineInfo ) {
+        registerTestCase(   new MethodTestCase<C>( method ),
+                            className,
+                            nameAndDesc,
+                            lineInfo );
+    }
+
+    void registerTestCase(  ITestCase* testCase,
+                            char const* className,
+                            NameAndDesc const& nameAndDesc,
+                            SourceLineInfo const& lineInfo );
+
+    ~AutoReg();
+
+private:
+    AutoReg( AutoReg const& );
+    void operator= ( AutoReg const& );
+};
+
+} // end namespace Catch
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TESTCASE( ... ) \
+        static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME(  ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
+        static void INTERNAL_CATCH_UNIQUE_NAME(  ____C_A_T_C_H____T_E_S_T____ )()
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
+        namespace{ \
+            struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
+                void test(); \
+            }; \
+            Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
+        } \
+        void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
+
+#else
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
+        static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME(  ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
+        static void INTERNAL_CATCH_UNIQUE_NAME(  ____C_A_T_C_H____T_E_S_T____ )()
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
+        namespace{ \
+            struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
+                void test(); \
+            }; \
+            Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
+        } \
+        void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
+
+#endif
+
+// #included from: internal/catch_capture.hpp
+#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
+
+// #included from: catch_expression_decomposer.hpp
+#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
+
+// #included from: catch_expression_lhs.hpp
+#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
+
+// #included from: catch_expressionresult_builder.h
+#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
+
+// #included from: catch_tostring.h
+#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
+
+// #included from: catch_sfinae.hpp
+#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
+
+// Try to detect if the current compiler supports SFINAE
+
+namespace Catch {
+
+    struct TrueType {
+        static const bool value = true;
+        typedef void Enable;
+        char sizer[1];
+    };
+    struct FalseType {
+        static const bool value = false;
+        typedef void Disable;
+        char sizer[2];
+    };
+
+#ifdef CATCH_CONFIG_SFINAE
+
+    template<bool> struct NotABooleanExpression;
+
+    template<bool c> struct If : NotABooleanExpression<c> {};
+    template<> struct If<true> : TrueType {};
+    template<> struct If<false> : FalseType {};
+
+    template<int size> struct SizedIf;
+    template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
+    template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
+
+#endif // CATCH_CONFIG_SFINAE
+
+} // end namespace Catch
+
+#include <sstream>
+#include <iomanip>
+#include <limits>
+#include <vector>
+#include <cstddef>
+
+#ifdef __OBJC__
+// #included from: catch_objc_arc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
+
+#import <Foundation/Foundation.h>
+
+#ifdef __has_feature
+#define CATCH_ARC_ENABLED __has_feature(objc_arc)
+#else
+#define CATCH_ARC_ENABLED 0
+#endif
+
+void arcSafeRelease( NSObject* obj );
+id performOptionalSelector( id obj, SEL sel );
+
+#if !CATCH_ARC_ENABLED
+inline void arcSafeRelease( NSObject* obj ) {
+    [obj release];
+}
+inline id performOptionalSelector( id obj, SEL sel ) {
+    if( [obj respondsToSelector: sel] )
+        return [obj performSelector: sel];
+    return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED
+#define CATCH_ARC_STRONG
+#else
+inline void arcSafeRelease( NSObject* ){}
+inline id performOptionalSelector( id obj, SEL sel ) {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+#endif
+    if( [obj respondsToSelector: sel] )
+        return [obj performSelector: sel];
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+    return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
+#define CATCH_ARC_STRONG __strong
+#endif
+
+#endif
+
+namespace Catch {
+namespace Detail {
+
+// SFINAE is currently disabled by default for all compilers.
+// If the non SFINAE version of IsStreamInsertable is ambiguous for you
+// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE
+#ifdef CATCH_CONFIG_SFINAE
+
+    template<typename T>
+    class IsStreamInsertableHelper {
+        template<int N> struct TrueIfSizeable : TrueType {};
+
+        template<typename T2>
+        static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
+        static FalseType dummy(...);
+
+    public:
+        typedef SizedIf<sizeof(dummy((T*)0))> type;
+    };
+
+    template<typename T>
+    struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {};
+
+#else
+
+    struct BorgType {
+        template<typename T> BorgType( T const& );
+    };
+
+    TrueType& testStreamable( std::ostream& );
+    FalseType testStreamable( FalseType );
+
+    FalseType operator<<( std::ostream const&, BorgType const& );
+
+    template<typename T>
+    struct IsStreamInsertable {
+        static std::ostream &s;
+        static T  const&t;
+        enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
+    };
+
+#endif
+
+    template<bool C>
+    struct StringMakerBase {
+        template<typename T>
+        static std::string convert( T const& ) { return "{?}"; }
+    };
+
+    template<>
+    struct StringMakerBase<true> {
+        template<typename T>
+        static std::string convert( T const& _value ) {
+            std::ostringstream oss;
+            oss << _value;
+            return oss.str();
+        }
+    };
+
+    struct Endianness {
+        enum Arch { Big, Little };
+
+        static Arch which() {
+            union {
+                int asInt;
+                char asChar[sizeof (int)];
+            };
+
+            asInt = 1;
+            return ( asChar[sizeof(int)-1] == 1 ) ? Big : Little;
+        }
+    };
+
+    // Writes the raw memory into a string, considering endianness
+    template<typename T>
+    std::string rawMemoryToString( T value ) {
+        union {
+            T typedValue;
+            unsigned char bytes[sizeof(T)];
+        };
+
+        typedValue = value;
+
+        std::ostringstream oss;
+        oss << "0x";
+
+        int i = 0, end = sizeof(T), inc = 1;
+        if( Endianness::which() == Endianness::Little ) {
+            i = end-1;
+            end = inc = -1;
+        }
+        for( ; i != end; i += inc )
+            oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)bytes[i];
+        return oss.str();
+    }
+
+} // end namespace Detail
+
+template<typename T>
+std::string toString( T const& value );
+
+template<typename T>
+struct StringMaker :
+    Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
+
+template<typename T>
+struct StringMaker<T*> {
+    template<typename U>
+    static std::string convert( U* p ) {
+        if( !p )
+            return INTERNAL_CATCH_STRINGIFY( NULL );
+        else
+            return Detail::rawMemoryToString( p );
+    }
+};
+
+template<typename R, typename C>
+struct StringMaker<R C::*> {
+    static std::string convert( R C::* p ) {
+        if( !p )
+            return INTERNAL_CATCH_STRINGIFY( NULL );
+        else
+            return Detail::rawMemoryToString( p );
+    }
+};
+
+namespace Detail {
+    template<typename InputIterator>
+    std::string rangeToString( InputIterator first, InputIterator last );
+}
+
+template<typename T, typename Allocator>
+struct StringMaker<std::vector<T, Allocator> > {
+    static std::string convert( std::vector<T,Allocator> const& v ) {
+        return Detail::rangeToString( v.begin(), v.end() );
+    }
+};
+
+namespace Detail {
+    template<typename T>
+    std::string makeString( T const& value ) {
+        return StringMaker<T>::convert( value );
+    }
+} // end namespace Detail
+
+/// \brief converts any type to a string
+///
+/// The default template forwards on to ostringstream - except when an
+/// ostringstream overload does not exist - in which case it attempts to detect
+/// that and writes {?}.
+/// Overload (not specialise) this template for custom typs that you don't want
+/// to provide an ostream overload for.
+template<typename T>
+std::string toString( T const& value ) {
+    return StringMaker<T>::convert( value );
+}
+
+// Built in overloads
+
+std::string toString( std::string const& value );
+std::string toString( std::wstring const& value );
+std::string toString( const char* const value );
+std::string toString( char* const value );
+std::string toString( int value );
+std::string toString( unsigned long value );
+std::string toString( unsigned int value );
+std::string toString( const double value );
+std::string toString( bool value );
+std::string toString( char value );
+std::string toString( signed char value );
+std::string toString( unsigned char value );
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+std::string toString( std::nullptr_t );
+#endif
+
+#ifdef __OBJC__
+    std::string toString( NSString const * const& nsstring );
+    std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
+    std::string toString( NSObject* const& nsObject );
+#endif
+
+    namespace Detail {
+    template<typename InputIterator>
+    std::string rangeToString( InputIterator first, InputIterator last ) {
+        std::ostringstream oss;
+        oss << "{ ";
+        if( first != last ) {
+            oss << toString( *first );
+            for( ++first ; first != last ; ++first ) {
+                oss << ", " << toString( *first );
+            }
+        }
+        oss << " }";
+        return oss.str();
+    }
+}
+
+} // end namespace Catch
+
+// #included from: catch_assertionresult.h
+#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
+
+#include <string>
+// #included from: catch_result_type.h
+#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
+
+namespace Catch {
+
+    // ResultWas::OfType enum
+    struct ResultWas { enum OfType {
+        Unknown = -1,
+        Ok = 0,
+        Info = 1,
+        Warning = 2,
+
+        FailureBit = 0x10,
+
+        ExpressionFailed = FailureBit | 1,
+        ExplicitFailure = FailureBit | 2,
+
+        Exception = 0x100 | FailureBit,
+
+        ThrewException = Exception | 1,
+        DidntThrowException = Exception | 2
+
+    }; };
+
+    inline bool isOk( ResultWas::OfType resultType ) {
+        return ( resultType & ResultWas::FailureBit ) == 0;
+    }
+    inline bool isJustInfo( int flags ) {
+        return flags == ResultWas::Info;
+    }
+
+    // ResultAction::Value enum
+    struct ResultAction { enum Value {
+        None,
+        Failed = 1, // Failure - but no debug break if Debug bit not set
+        Debug = 2,  // If this bit is set, invoke the debugger
+        Abort = 4   // Test run should abort
+    }; };
+
+    // ResultDisposition::Flags enum
+    struct ResultDisposition { enum Flags {
+            Normal = 0x00,
+
+            ContinueOnFailure = 0x01,   // Failures fail test, but execution continues
+            NegateResult = 0x02,        // Prefix expressiom with !
+            SuppressFail = 0x04         // Failures are reported but do not fail the test
+    }; };
+
+    inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
+        return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
+    }
+
+    inline bool shouldContinueOnFailure( int flags )    { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
+    inline bool shouldNegate( int flags )               { return ( flags & ResultDisposition::NegateResult ) != 0; }
+    inline bool shouldSuppressFailure( int flags )      { return ( flags & ResultDisposition::SuppressFail ) != 0; }
+
+} // end namespace Catch
+
+
+namespace Catch {
+
+    struct AssertionInfo
+    {
+        AssertionInfo() {}
+        AssertionInfo(  std::string const& _macroName,
+                        SourceLineInfo const& _lineInfo,
+                        std::string const& _capturedExpression,
+                        ResultDisposition::Flags _resultDisposition );
+
+        std::string macroName;
+        SourceLineInfo lineInfo;
+        std::string capturedExpression;
+        ResultDisposition::Flags resultDisposition;
+    };
+
+    struct AssertionResultData
+    {
+        AssertionResultData() : resultType( ResultWas::Unknown ) {}
+
+        std::string reconstructedExpression;
+        std::string message;
+        ResultWas::OfType resultType;
+    };
+
+    class AssertionResult {
+    public:
+        AssertionResult();
+        AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
+        ~AssertionResult();
+#  ifdef CATCH_CPP11_OR_GREATER
+         AssertionResult( AssertionResult const& )              = default;
+         AssertionResult( AssertionResult && )                  = default;
+         AssertionResult& operator = ( AssertionResult const& ) = default;
+         AssertionResult& operator = ( AssertionResult && )     = default;
+#  endif
+
+        bool isOk() const;
+        bool succeeded() const;
+        ResultWas::OfType getResultType() const;
+        bool hasExpression() const;
+        bool hasMessage() const;
+        std::string getExpression() const;
+        std::string getExpressionInMacro() const;
+        bool hasExpandedExpression() const;
+        std::string getExpandedExpression() const;
+        std::string getMessage() const;
+        SourceLineInfo getSourceInfo() const;
+        std::string getTestMacroName() const;
+
+    protected:
+        AssertionInfo m_info;
+        AssertionResultData m_resultData;
+    };
+
+} // end namespace Catch
+
+// #included from: catch_evaluate.hpp
+#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+#endif
+
+#include <cstddef>
+
+namespace Catch {
+namespace Internal {
+
+    enum Operator {
+        IsEqualTo,
+        IsNotEqualTo,
+        IsLessThan,
+        IsGreaterThan,
+        IsLessThanOrEqualTo,
+        IsGreaterThanOrEqualTo
+    };
+
+    template<Operator Op> struct OperatorTraits             { static const char* getName(){ return "*error*"; } };
+    template<> struct OperatorTraits<IsEqualTo>             { static const char* getName(){ return "=="; } };
+    template<> struct OperatorTraits<IsNotEqualTo>          { static const char* getName(){ return "!="; } };
+    template<> struct OperatorTraits<IsLessThan>            { static const char* getName(){ return "<"; } };
+    template<> struct OperatorTraits<IsGreaterThan>         { static const char* getName(){ return ">"; } };
+    template<> struct OperatorTraits<IsLessThanOrEqualTo>   { static const char* getName(){ return "<="; } };
+    template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
+
+    template<typename T>
+    inline T& opCast(T const& t) { return const_cast<T&>(t); }
+
+// nullptr_t support based on pull request #154 from Konstantin Baumann
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+    inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
+#endif // CATCH_CONFIG_CPP11_NULLPTR
+
+    // So the compare overloads can be operator agnostic we convey the operator as a template
+    // enum, which is used to specialise an Evaluator for doing the comparison.
+    template<typename T1, typename T2, Operator Op>
+    class Evaluator{};
+
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsEqualTo> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs) {
+            return opCast( lhs ) ==  opCast( rhs );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsNotEqualTo> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return opCast( lhs ) != opCast( rhs );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsLessThan> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return opCast( lhs ) < opCast( rhs );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsGreaterThan> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return opCast( lhs ) > opCast( rhs );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return opCast( lhs ) >= opCast( rhs );
+        }
+    };
+    template<typename T1, typename T2>
+    struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
+        static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+            return opCast( lhs ) <= opCast( rhs );
+        }
+    };
+
+    template<Operator Op, typename T1, typename T2>
+    bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
+        return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+    }
+
+    // This level of indirection allows us to specialise for integer types
+    // to avoid signed/ unsigned warnings
+
+    // "base" overload
+    template<Operator Op, typename T1, typename T2>
+    bool compare( T1 const& lhs, T2 const& rhs ) {
+        return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+    }
+
+    // unsigned X to int
+    template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+    }
+    template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+    }
+    template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+    }
+
+    // unsigned X to long
+    template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+    }
+    template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+    }
+    template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
+        return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+    }
+
+    // int to unsigned X
+    template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+    }
+
+    // long to unsigned X
+    template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+    template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
+        return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+    }
+
+    // pointer to long (when comparing against NULL)
+    template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+    }
+    template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+    }
+
+    // pointer to int (when comparing against NULL)
+    template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+    }
+    template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+    }
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+    // pointer to nullptr_t (when comparing against nullptr)
+    template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
+        return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
+    }
+    template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
+        return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
+    }
+#endif // CATCH_CONFIG_CPP11_NULLPTR
+
+} // end of namespace Internal
+} // end of namespace Catch
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+namespace Catch {
+
+struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
+
+// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as
+// the result of evaluating it. This is used to build an AssertionResult object
+class ExpressionResultBuilder {
+public:
+
+    ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown );
+    ExpressionResultBuilder( ExpressionResultBuilder const& other );
+    ExpressionResultBuilder& operator=(ExpressionResultBuilder const& other );
+
+    ExpressionResultBuilder& setResultType( ResultWas::OfType result );
+    ExpressionResultBuilder& setResultType( bool result );
+    ExpressionResultBuilder& setLhs( std::string const& lhs );
+    ExpressionResultBuilder& setRhs( std::string const& rhs );
+    ExpressionResultBuilder& setOp( std::string const& op );
+
+    ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition );
+
+    template<typename T>
+    ExpressionResultBuilder& operator << ( T const& value ) {
+        m_stream << value;
+        return *this;
+    }
+
+    std::string reconstructExpression( AssertionInfo const& info ) const;
+
+    AssertionResult buildResult( AssertionInfo const& info ) const;
+
+    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
+    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
+
+private:
+    AssertionResultData m_data;
+    struct ExprComponents {
+        ExprComponents() : shouldNegate( false ) {}
+        bool shouldNegate;
+        std::string lhs, rhs, op;
+    } m_exprComponents;
+    std::ostringstream m_stream;
+};
+
+} // end namespace Catch
+
+namespace Catch {
+
+// Wraps the LHS of an expression and captures the operator and RHS (if any) -
+// wrapping them all in an ExpressionResultBuilder object
+template<typename T>
+class ExpressionLhs {
+    ExpressionLhs& operator = ( ExpressionLhs const& );
+#  ifdef CATCH_CPP11_OR_GREATER
+    ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
+#  endif
+
+public:
+    ExpressionLhs( T lhs ) : m_lhs( lhs ) {}
+#  ifdef CATCH_CPP11_OR_GREATER
+    ExpressionLhs( ExpressionLhs const& ) = default;
+    ExpressionLhs( ExpressionLhs && )     = default;
+#  endif
+
+    template<typename RhsT>
+    ExpressionResultBuilder& operator == ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsEqualTo>( rhs );
+    }
+
+    template<typename RhsT>
+    ExpressionResultBuilder& operator != ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsNotEqualTo>( rhs );
+    }
+
+    template<typename RhsT>
+    ExpressionResultBuilder& operator < ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsLessThan>( rhs );
+    }
+
+    template<typename RhsT>
+    ExpressionResultBuilder& operator > ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsGreaterThan>( rhs );
+    }
+
+    template<typename RhsT>
+    ExpressionResultBuilder& operator <= ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
+    }
+
+    template<typename RhsT>
+    ExpressionResultBuilder& operator >= ( RhsT const& rhs ) {
+        return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
+    }
+
+    ExpressionResultBuilder& operator == ( bool rhs ) {
+        return captureExpression<Internal::IsEqualTo>( rhs );
+    }
+
+    ExpressionResultBuilder& operator != ( bool rhs ) {
+        return captureExpression<Internal::IsNotEqualTo>( rhs );
+    }
+
+    ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) {
+        bool value = m_lhs ? true : false;
+        return m_result
+            .setLhs( Catch::toString( value ) )
+            .setResultType( value )
+            .endExpression( resultDisposition );
+    }
+
+    // Only simple binary expressions are allowed on the LHS.
+    // If more complex compositions are required then place the sub expression in parentheses
+    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
+    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
+    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
+    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
+    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
+    template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
+
+private:
+    template<Internal::Operator Op, typename RhsT>
+    ExpressionResultBuilder& captureExpression( RhsT const& rhs ) {
+        return m_result
+            .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
+            .setLhs( Catch::toString( m_lhs ) )
+            .setRhs( Catch::toString( rhs ) )
+            .setOp( Internal::OperatorTraits<Op>::getName() );
+    }
+
+private:
+    ExpressionResultBuilder m_result;
+    T m_lhs;
+};
+
+} // end namespace Catch
+
+namespace Catch {
+
+// Captures the LHS of the expression and wraps it in an Expression Lhs object
+class ExpressionDecomposer {
+public:
+
+    template<typename T>
+    ExpressionLhs<T const&> operator->* ( T const& operand ) {
+        return ExpressionLhs<T const&>( operand );
+    }
+
+    ExpressionLhs<bool> operator->* ( bool value ) {
+        return ExpressionLhs<bool>( value );
+    }
+};
+
+} // end namespace Catch
+
+// #included from: catch_message.h
+#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    struct MessageInfo {
+        MessageInfo(    std::string const& _macroName,
+                        SourceLineInfo const& _lineInfo,
+                        ResultWas::OfType _type );
+
+        std::string macroName;
+        SourceLineInfo lineInfo;
+        ResultWas::OfType type;
+        std::string message;
+        unsigned int sequence;
+
+        bool operator == ( MessageInfo const& other ) const {
+            return sequence == other.sequence;
+        }
+        bool operator < ( MessageInfo const& other ) const {
+            return sequence < other.sequence;
+        }
+    private:
+        static unsigned int globalCount;
+    };
+
+    struct MessageBuilder {
+        MessageBuilder( std::string const& macroName,
+                        SourceLineInfo const& lineInfo,
+                        ResultWas::OfType type )
+        : m_info( macroName, lineInfo, type )
+        {}
+
+        template<typename T>
+        MessageBuilder& operator << ( T const& value ) {
+            m_stream << value;
+            return *this;
+        }
+
+        MessageInfo m_info;
+        std::ostringstream m_stream;
+    };
+
+    class ScopedMessage {
+    public:
+        ScopedMessage( MessageBuilder const& builder );
+        ~ScopedMessage();
+
+        MessageInfo m_info;
+    };
+
+} // end namespace Catch
+
+// #included from: catch_interfaces_capture.h
+#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    class TestCase;
+    class ExpressionResultBuilder;
+    class AssertionResult;
+    struct AssertionInfo;
+    struct SectionInfo;
+    struct MessageInfo;
+    class ScopedMessageBuilder;
+    struct Counts;
+
+    struct IResultCapture {
+
+        virtual ~IResultCapture();
+
+        virtual void assertionEnded( AssertionResult const& result ) = 0;
+        virtual bool sectionStarted(    SectionInfo const& sectionInfo,
+                                        Counts& assertions ) = 0;
+        virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
+        virtual void pushScopedMessage( MessageInfo const& message ) = 0;
+        virtual void popScopedMessage( MessageInfo const& message ) = 0;
+
+        virtual bool shouldDebugBreak() const = 0;
+
+        virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0;
+
+        virtual std::string getCurrentTestName() const = 0;
+        virtual const AssertionResult* getLastResult() const = 0;
+    };
+}
+
+// #included from: catch_debugger.h
+#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
+
+// #included from: catch_platform.h
+#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
+
+#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
+#define CATCH_PLATFORM_MAC
+#elif  defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+#define CATCH_PLATFORM_IPHONE
+#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
+#define CATCH_PLATFORM_WINDOWS
+#endif
+
+#include <string>
+
+namespace Catch{
+
+    bool isDebuggerActive();
+    void writeToDebugConsole( std::string const& text );
+}
+
+#ifdef CATCH_PLATFORM_MAC
+
+    // The following code snippet based on:
+    // http://cocoawithlove.com/2008/03/break-into-debugger.html
+    #ifdef DEBUG
+        #if defined(__ppc64__) || defined(__ppc__)
+            #define CATCH_BREAK_INTO_DEBUGGER() \
+                if( Catch::isDebuggerActive() ) { \
+                    __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
+                    : : : "memory","r0","r3","r4" ); \
+                }
+        #else
+            #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
+        #endif
+    #endif
+
+#elif defined(_MSC_VER)
+    #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
+#elif defined(__MINGW32__)
+    extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+    #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
+#endif
+
+#ifndef CATCH_BREAK_INTO_DEBUGGER
+#define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true );
+#endif
+
+// #included from: catch_interfaces_registry_hub.h
+#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    class TestCase;
+    struct ITestCaseRegistry;
+    struct IExceptionTranslatorRegistry;
+    struct IExceptionTranslator;
+    struct IReporterRegistry;
+    struct IReporterFactory;
+
+    struct IRegistryHub {
+        virtual ~IRegistryHub();
+
+        virtual IReporterRegistry const& getReporterRegistry() const = 0;
+        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
+        virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
+    };
+
+    struct IMutableRegistryHub {
+        virtual ~IMutableRegistryHub();
+        virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
+        virtual void registerTest( TestCase const& testInfo ) = 0;
+        virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
+    };
+
+    IRegistryHub& getRegistryHub();
+    IMutableRegistryHub& getMutableRegistryHub();
+    void cleanUp();
+    std::string translateActiveException();
+
+}
+
+// #included from: catch_interfaces_config.h
+#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace Catch {
+
+    struct Verbosity { enum Level {
+        NoOutput = 0,
+        Quiet,
+        Normal
+    }; };
+
+    struct WarnAbout { enum What {
+        Nothing = 0x00,
+        NoAssertions = 0x01
+    }; };
+
+    struct ShowDurations { enum OrNot {
+        DefaultForReporter,
+        Always,
+        Never
+    }; };
+
+    class TestCaseFilters;
+
+    struct IConfig : IShared {
+
+        virtual ~IConfig();
+
+        virtual bool allowThrows() const = 0;
+        virtual std::ostream& stream() const = 0;
+        virtual std::string name() const = 0;
+        virtual bool includeSuccessfulResults() const = 0;
+        virtual bool shouldDebugBreak() const = 0;
+        virtual bool warnAboutMissingAssertions() const = 0;
+        virtual int abortAfter() const = 0;
+        virtual bool showInvisibles() const = 0;
+        virtual ShowDurations::OrNot showDurations() const = 0;
+        virtual std::vector<TestCaseFilters> const& filters() const = 0;
+    };
+}
+
+#include <ostream>
+
+namespace Catch {
+
+    inline IResultCapture& getResultCapture() {
+        return getCurrentContext().getResultCapture();
+    }
+
+    template<typename MatcherT>
+    ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
+                                                                std::string const& matcherCallAsString ) {
+        std::string matcherAsString = matcher.toString();
+        if( matcherAsString == "{?}" )
+            matcherAsString = matcherCallAsString;
+        return ExpressionResultBuilder()
+            .setRhs( matcherAsString )
+            .setOp( "matches" );
+    }
+
+    template<typename MatcherT, typename ArgT>
+    ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
+                                                                ArgT const& arg,
+                                                                std::string const& matcherCallAsString ) {
+        return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
+            .setLhs( Catch::toString( arg ) )
+            .setResultType( matcher.match( arg ) );
+    }
+
+    template<typename MatcherT, typename ArgT>
+    ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
+                                                                ArgT* arg,
+                                                                std::string const& matcherCallAsString ) {
+        return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
+            .setLhs( Catch::toString( arg ) )
+            .setResultType( matcher.match( arg ) );
+    }
+
+struct TestFailureException{};
+
+} // end namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
+    if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, __assertionInfo )  ) { \
+        if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \
+        if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
+        if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
+        Catch::isTrue( false && originalExpr ); \
+    }
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
+    do { \
+        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        try { \
+            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
+        } catch( Catch::TestFailureException& ) { \
+            throw; \
+        } catch( ... ) { \
+            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
+                Catch::ResultDisposition::Normal, expr ); \
+        } \
+    } while( Catch::isTrue( false ) )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
+    INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
+    if( Catch::getResultCapture().getLastResult()->succeeded() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
+    INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
+    if( !Catch::getResultCapture().getLastResult()->succeeded() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
+    do { \
+        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        try { \
+            expr; \
+            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
+        } \
+        catch( ... ) { \
+            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \
+        } \
+} while( Catch::isTrue( false ) )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
+    try { \
+        if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
+            expr; \
+            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
+        } \
+    } \
+    catch( Catch::TestFailureException& ) { \
+        throw; \
+    } \
+    catch( exceptionType ) { \
+        INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
+    }
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
+    do { \
+        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
+    } while( Catch::isTrue( false ) )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
+    do { \
+        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+        INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
+        catch( ... ) { \
+            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
+                resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
+        } \
+    } while( Catch::isTrue( false ) )
+
+///////////////////////////////////////////////////////////////////////////////
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+    #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
+        do { \
+            Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \
+        } while( Catch::isTrue( false ) )
+#else
+    #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
+        do { \
+            Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+            INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \
+        } while( Catch::isTrue( false ) )
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_INFO( log, macroName ) \
+    Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
+    do { \
+        Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
+        try { \
+            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
+        } catch( Catch::TestFailureException& ) { \
+            throw; \
+        } catch( ... ) { \
+            INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
+                resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
+        } \
+    } while( Catch::isTrue( false ) )
+
+// #included from: internal/catch_section.h
+#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
+
+// #included from: catch_section_info.h
+#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
+
+namespace Catch {
+
+    struct SectionInfo {
+        SectionInfo(    std::string const& _name,
+                        std::string const& _description,
+                        SourceLineInfo const& _lineInfo )
+        :   name( _name ),
+            description( _description ),
+            lineInfo( _lineInfo )
+        {}
+
+        std::string name;
+        std::string description;
+        SourceLineInfo lineInfo;
+    };
+
+} // end namespace Catch
+
+// #included from: catch_totals.hpp
+#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
+
+#include <cstddef>
+
+namespace Catch {
+
+    struct Counts {
+        Counts() : passed( 0 ), failed( 0 ) {}
+
+        Counts operator - ( Counts const& other ) const {
+            Counts diff;
+            diff.passed = passed - other.passed;
+            diff.failed = failed - other.failed;
+            return diff;
+        }
+        Counts& operator += ( Counts const& other ) {
+            passed += other.passed;
+            failed += other.failed;
+            return *this;
+        }
+
+        std::size_t total() const {
+            return passed + failed;
+        }
+
+        std::size_t passed;
+        std::size_t failed;
+    };
+
+    struct Totals {
+
+        Totals operator - ( Totals const& other ) const {
+            Totals diff;
+            diff.assertions = assertions - other.assertions;
+            diff.testCases = testCases - other.testCases;
+            return diff;
+        }
+
+        Totals delta( Totals const& prevTotals ) const {
+            Totals diff = *this - prevTotals;
+            if( diff.assertions.failed > 0 )
+                ++diff.testCases.failed;
+            else
+                ++diff.testCases.passed;
+            return diff;
+        }
+
+        Totals& operator += ( Totals const& other ) {
+            assertions += other.assertions;
+            testCases += other.testCases;
+            return *this;
+        }
+
+        Counts assertions;
+        Counts testCases;
+    };
+}
+
+// #included from: catch_timer.h
+#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
+
+#ifdef CATCH_PLATFORM_WINDOWS
+typedef unsigned long long uint64_t;
+#else
+#include <stdint.h>
+#endif
+
+namespace Catch {
+
+    class Timer {
+    public:
+        Timer() : m_ticks( 0 ) {}
+        void start();
+        unsigned int getElapsedNanoseconds() const;
+        unsigned int getElapsedMilliseconds() const;
+        double getElapsedSeconds() const;
+
+    private:
+        uint64_t m_ticks;
+    };
+
+} // namespace Catch
+
+#include <string>
+
+namespace Catch {
+
+    class Section {
+    public:
+        Section(    SourceLineInfo const& lineInfo,
+                    std::string const& name,
+                    std::string const& description = "" );
+        ~Section();
+#  ifdef CATCH_CPP11_OR_GREATER
+        Section( Section const& )              = default;
+        Section( Section && )                  = default;
+        Section& operator = ( Section const& ) = default;
+        Section& operator = ( Section && )     = default;
+#  endif
+
+        // This indicates whether the section should be executed or not
+        operator bool();
+
+    private:
+
+        SectionInfo m_info;
+
+        std::string m_name;
+        Counts m_assertions;
+        bool m_sectionIncluded;
+        Timer m_timer;
+    };
+
+} // end namespace Catch
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+    #define INTERNAL_CATCH_SECTION( ... ) \
+        if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
+#else
+    #define INTERNAL_CATCH_SECTION( name, desc ) \
+        if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) )
+#endif
+
+// #included from: internal/catch_generators.hpp
+#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
+
+#include <iterator>
+#include <vector>
+#include <string>
+#include <stdlib.h>
+
+namespace Catch {
+
+template<typename T>
+struct IGenerator {
+    virtual ~IGenerator() {}
+    virtual T getValue( std::size_t index ) const = 0;
+    virtual std::size_t size () const = 0;
+};
+
+template<typename T>
+class BetweenGenerator : public IGenerator<T> {
+public:
+    BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
+
+    virtual T getValue( std::size_t index ) const {
+        return m_from+static_cast<int>( index );
+    }
+
+    virtual std::size_t size() const {
+        return static_cast<std::size_t>( 1+m_to-m_from );
+    }
+
+private:
+
+    T m_from;
+    T m_to;
+};
+
+template<typename T>
+class ValuesGenerator : public IGenerator<T> {
+public:
+    ValuesGenerator(){}
+
+    void add( T value ) {
+        m_values.push_back( value );
+    }
+
+    virtual T getValue( std::size_t index ) const {
+        return m_values[index];
+    }
+
+    virtual std::size_t size() const {
+        return m_values.size();
+    }
+
+private:
+    std::vector<T> m_values;
+};
+
+template<typename T>
+class CompositeGenerator {
+public:
+    CompositeGenerator() : m_totalSize( 0 ) {}
+
+    // *** Move semantics, similar to auto_ptr ***
+    CompositeGenerator( CompositeGenerator& other )
+    :   m_fileInfo( other.m_fileInfo ),
+        m_totalSize( 0 )
+    {
+        move( other );
+    }
+
+    CompositeGenerator& setFileInfo( const char* fileInfo ) {
+        m_fileInfo = fileInfo;
+        return *this;
+    }
+
+    ~CompositeGenerator() {
+        deleteAll( m_composed );
+    }
+
+    operator T () const {
+        size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
+
+        typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
+        typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
+        for( size_t index = 0; it != itEnd; ++it )
+        {
+            const IGenerator<T>* generator = *it;
+            if( overallIndex >= index && overallIndex < index + generator->size() )
+            {
+                return generator->getValue( overallIndex-index );
+            }
+            index += generator->size();
+        }
+        CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
+        return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
+    }
+
+    void add( const IGenerator<T>* generator ) {
+        m_totalSize += generator->size();
+        m_composed.push_back( generator );
+    }
+
+    CompositeGenerator& then( CompositeGenerator& other ) {
+        move( other );
+        return *this;
+    }
+
+    CompositeGenerator& then( T value ) {
+        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+        valuesGen->add( value );
+        add( valuesGen );
+        return *this;
+    }
+
+private:
+
+    void move( CompositeGenerator& other ) {
+        std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
+        m_totalSize += other.m_totalSize;
+        other.m_composed.clear();
+    }
+
+    std::vector<const IGenerator<T>*> m_composed;
+    std::string m_fileInfo;
+    size_t m_totalSize;
+};
+
+namespace Generators
+{
+    template<typename T>
+    CompositeGenerator<T> between( T from, T to ) {
+        CompositeGenerator<T> generators;
+        generators.add( new BetweenGenerator<T>( from, to ) );
+        return generators;
+    }
+
+    template<typename T>
+    CompositeGenerator<T> values( T val1, T val2 ) {
+        CompositeGenerator<T> generators;
+        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+        valuesGen->add( val1 );
+        valuesGen->add( val2 );
+        generators.add( valuesGen );
+        return generators;
+    }
+
+    template<typename T>
+    CompositeGenerator<T> values( T val1, T val2, T val3 ){
+        CompositeGenerator<T> generators;
+        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+        valuesGen->add( val1 );
+        valuesGen->add( val2 );
+        valuesGen->add( val3 );
+        generators.add( valuesGen );
+        return generators;
+    }
+
+    template<typename T>
+    CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
+        CompositeGenerator<T> generators;
+        ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+        valuesGen->add( val1 );
+        valuesGen->add( val2 );
+        valuesGen->add( val3 );
+        valuesGen->add( val4 );
+        generators.add( valuesGen );
+        return generators;
+    }
+
+} // end namespace Generators
+
+using namespace Generators;
+
+} // end namespace Catch
+
+#define INTERNAL_CATCH_LINESTR2( line ) #line
+#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
+
+#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
+
+// #included from: internal/catch_interfaces_exception.h
+#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+    typedef std::string(*exceptionTranslateFunction)();
+
+    struct IExceptionTranslator {
+        virtual ~IExceptionTranslator();
+        virtual std::string translate() const = 0;
+    };
+
+    struct IExceptionTranslatorRegistry {
+        virtual ~IExceptionTranslatorRegistry();
+
+        virtual std::string translateActiveException() const = 0;
+    };
+
+    class ExceptionTranslatorRegistrar {
+        template<typename T>
+        class ExceptionTranslator : public IExceptionTranslator {
+        public:
+
+            ExceptionTranslator( std::string(*translateFunction)( T& ) )
+            : m_translateFunction( translateFunction )
+            {}
+
+            virtual std::string translate() const {
+                try {
+                    throw;
+                }
+                catch( T& ex ) {
+                    return m_translateFunction( ex );
+                }
+            }
+
+        protected:
+            std::string(*m_translateFunction)( T& );
+        };
+
+    public:
+        template<typename T>
+        ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
+            getMutableRegistryHub().registerTranslator
+                ( new ExceptionTranslator<T>( translateFunction ) );
+        }
+    };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
+    static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
+    namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
+    static std::string INTERNAL_CATCH_UNIQUE_NAME(  catch_internal_ExceptionTranslator )( signature )
+
+// #included from: internal/catch_approx.hpp
+#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
+
+#include <cmath>
+#include <limits>
+
+namespace Catch {
+namespace Detail {
+
+    class Approx {
+    public:
+        explicit Approx ( double value )
+        :   m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
+            m_scale( 1.0 ),
+            m_value( value )
+        {}
+
+        Approx( Approx const& other )
+        :   m_epsilon( other.m_epsilon ),
+            m_scale( other.m_scale ),
+            m_value( other.m_value )
+        {}
+
+        static Approx custom() {
+            return Approx( 0 );
+        }
+
+        Approx operator()( double value ) {
+            Approx approx( value );
+            approx.epsilon( m_epsilon );
+            approx.scale( m_scale );
+            return approx;
+        }
+
+        friend bool operator == ( double lhs, Approx const& rhs ) {
+            // Thanks to Richard Harris for his help refining this formula
+            return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
+        }
+
+        friend bool operator == ( Approx const& lhs, double rhs ) {
+            return operator==( rhs, lhs );
+        }
+
+        friend bool operator != ( double lhs, Approx const& rhs ) {
+            return !operator==( lhs, rhs );
+        }
+
+        friend bool operator != ( Approx const& lhs, double rhs ) {
+            return !operator==( rhs, lhs );
+        }
+
+        Approx& epsilon( double newEpsilon ) {
+            m_epsilon = newEpsilon;
+            return *this;
+        }
+
+        Approx& scale( double newScale ) {
+            m_scale = newScale;
+            return *this;
+        }
+
+        std::string toString() const {
+            std::ostringstream oss;
+            oss << "Approx( " << Catch::toString( m_value ) << " )";
+            return oss.str();
+        }
+
+    private:
+        double m_epsilon;
+        double m_scale;
+        double m_value;
+    };
+}
+
+template<>
+inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
+    return value.toString();
+}
+
+} // end namespace Catch
+
+// #included from: internal/catch_matchers.hpp
+#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+    namespace Impl {
+
+    template<typename ExpressionT>
+    struct Matcher : SharedImpl<IShared>
+    {
+        typedef ExpressionT ExpressionType;
+
+        virtual ~Matcher() {}
+        virtual Ptr<Matcher> clone() const = 0;
+        virtual bool match( ExpressionT const& expr ) const = 0;
+        virtual std::string toString() const = 0;
+    };
+
+    template<typename DerivedT, typename ExpressionT>
+    struct MatcherImpl : Matcher<ExpressionT> {
+
+        virtual Ptr<Matcher<ExpressionT> > clone() const {
+            return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
+        }
+    };
+
+    namespace Generic {
+
+        template<typename ExpressionT>
+        class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
+        public:
+
+            AllOf() {}
+            AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
+
+            AllOf& add( Matcher<ExpressionT> const& matcher ) {
+                m_matchers.push_back( matcher.clone() );
+                return *this;
+            }
+            virtual bool match( ExpressionT const& expr ) const
+            {
+                for( std::size_t i = 0; i < m_matchers.size(); ++i )
+                    if( !m_matchers[i]->match( expr ) )
+                        return false;
+                return true;
+            }
+            virtual std::string toString() const {
+                std::ostringstream oss;
+                oss << "( ";
+                for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+                    if( i != 0 )
+                        oss << " and ";
+                    oss << m_matchers[i]->toString();
+                }
+                oss << " )";
+                return oss.str();
+            }
+
+        private:
+            std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
+        };
+
+        template<typename ExpressionT>
+        class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
+        public:
+
+            AnyOf() {}
+            AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
+
+            AnyOf& add( Matcher<ExpressionT> const& matcher ) {
+                m_matchers.push_back( matcher.clone() );
+                return *this;
+            }
+            virtual bool match( ExpressionT const& expr ) const
+            {
+                for( std::size_t i = 0; i < m_matchers.size(); ++i )
+                    if( m_matchers[i]->match( expr ) )
+                        return true;
+                return false;
+            }
+            virtual std::string toString() const {
+                std::ostringstream oss;
+                oss << "( ";
+                for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+                    if( i != 0 )
+                        oss << " or ";
+                    oss << m_matchers[i]->toString();
+                }
+                oss << " )";
+                return oss.str();
+            }
+
+        private:
+            std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
+        };
+
+    }
+
+    namespace StdString {
+
+        inline std::string makeString( std::string const& str ) { return str; }
+        inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
+
+        struct Equals : MatcherImpl<Equals, std::string> {
+            Equals( std::string const& str ) : m_str( str ){}
+            Equals( Equals const& other ) : m_str( other.m_str ){}
+
+            virtual ~Equals();
+
+            virtual bool match( std::string const& expr ) const {
+                return m_str == expr;
+            }
+            virtual std::string toString() const {
+                return "equals: \"" + m_str + "\"";
+            }
+
+            std::string m_str;
+        };
+
+        struct Contains : MatcherImpl<Contains, std::string> {
+            Contains( std::string const& substr ) : m_substr( substr ){}
+            Contains( Contains const& other ) : m_substr( other.m_substr ){}
+
+            virtual ~Contains();
+
+            virtual bool match( std::string const& expr ) const {
+                return expr.find( m_substr ) != std::string::npos;
+            }
+            virtual std::string toString() const {
+                return "contains: \"" + m_substr + "\"";
+            }
+
+            std::string m_substr;
+        };
+
+        struct StartsWith : MatcherImpl<StartsWith, std::string> {
+            StartsWith( std::string const& substr ) : m_substr( substr ){}
+            StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){}
+
+            virtual ~StartsWith();
+
+            virtual bool match( std::string const& expr ) const {
+                return expr.find( m_substr ) == 0;
+            }
+            virtual std::string toString() const {
+                return "starts with: \"" + m_substr + "\"";
+            }
+
+            std::string m_substr;
+        };
+
+        struct EndsWith : MatcherImpl<EndsWith, std::string> {
+            EndsWith( std::string const& substr ) : m_substr( substr ){}
+            EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){}
+
+            virtual ~EndsWith();
+
+            virtual bool match( std::string const& expr ) const {
+                return expr.find( m_substr ) == expr.size() - m_substr.size();
+            }
+            virtual std::string toString() const {
+                return "ends with: \"" + m_substr + "\"";
+            }
+
+            std::string m_substr;
+        };
+    } // namespace StdString
+    } // namespace Impl
+
+    // The following functions create the actual matcher objects.
+    // This allows the types to be inferred
+    template<typename ExpressionT>
+    inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+                                                    Impl::Matcher<ExpressionT> const& m2 ) {
+        return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
+    }
+    template<typename ExpressionT>
+    inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+                                                    Impl::Matcher<ExpressionT> const& m2,
+                                                    Impl::Matcher<ExpressionT> const& m3 ) {
+        return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
+    }
+    template<typename ExpressionT>
+    inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+                                                    Impl::Matcher<ExpressionT> const& m2 ) {
+        return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
+    }
+    template<typename ExpressionT>
+    inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+                                                    Impl::Matcher<ExpressionT> const& m2,
+                                                    Impl::Matcher<ExpressionT> const& m3 ) {
+        return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
+    }
+
+    inline Impl::StdString::Equals      Equals( std::string const& str ) {
+        return Impl::StdString::Equals( str );
+    }
+    inline Impl::StdString::Equals      Equals( const char* str ) {
+        return Impl::StdString::Equals( Impl::StdString::makeString( str ) );
+    }
+    inline Impl::StdString::Contains    Contains( std::string const& substr ) {
+        return Impl::StdString::Contains( substr );
+    }
+    inline Impl::StdString::Contains    Contains( const char* substr ) {
+        return Impl::StdString::Contains( Impl::StdString::makeString( substr ) );
+    }
+    inline Impl::StdString::StartsWith  StartsWith( std::string const& substr ) {
+        return Impl::StdString::StartsWith( substr );
+    }
+    inline Impl::StdString::StartsWith  StartsWith( const char* substr ) {
+        return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
+    }
+    inline Impl::StdString::EndsWith    EndsWith( std::string const& substr ) {
+        return Impl::StdString::EndsWith( substr );
+    }
+    inline Impl::StdString::EndsWith    EndsWith( const char* substr ) {
+        return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
+    }
+
+} // namespace Matchers
+
+using namespace Matchers;
+
+} // namespace Catch
+
+// These files are included here so the single_include script doesn't put them
+// in the conditionally compiled sections
+// #included from: internal/catch_test_case_info.h
+#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
+
+#include <string>
+#include <set>
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+    struct ITestCase;
+
+    struct TestCaseInfo {
+        TestCaseInfo(   std::string const& _name,
+                        std::string const& _className,
+                        std::string const& _description,
+                        std::set<std::string> const& _tags,
+                        bool _isHidden,
+                        SourceLineInfo const& _lineInfo );
+
+        TestCaseInfo( TestCaseInfo const& other );
+
+        std::string name;
+        std::string className;
+        std::string description;
+        std::set<std::string> tags;
+        std::string tagsAsString;
+        SourceLineInfo lineInfo;
+        bool isHidden;
+        bool throws;
+    };
+
+    class TestCase : protected TestCaseInfo {
+    public:
+
+        TestCase( ITestCase* testCase, TestCaseInfo const& info );
+        TestCase( TestCase const& other );
+
+        TestCase withName( std::string const& _newName ) const;
+
+        void invoke() const;
+
+        TestCaseInfo const& getTestCaseInfo() const;
+
+        bool isHidden() const;
+        bool throws() const;
+        bool hasTag( std::string const& tag ) const;
+        bool matchesTags( std::string const& tagPattern ) const;
+        std::set<std::string> const& getTags() const;
+
+        void swap( TestCase& other );
+        bool operator == ( TestCase const& other ) const;
+        bool operator < ( TestCase const& other ) const;
+        TestCase& operator = ( TestCase const& other );
+
+    private:
+        Ptr<ITestCase> test;
+    };
+
+    TestCase makeTestCase(  ITestCase* testCase,
+                            std::string const& className,
+                            std::string const& name,
+                            std::string const& description,
+                            SourceLineInfo const& lineInfo );
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+// #included from: internal/catch_interfaces_runner.h
+#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
+
+namespace Catch {
+    class TestCase;
+
+    struct IRunner {
+        virtual ~IRunner();
+    };
+}
+
+
+#ifdef __OBJC__
+// #included from: internal/catch_objc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
+
+#import <objc/runtime.h>
+
+#include <string>
+
+// NB. Any general catch headers included here must be included
+// in catch.hpp first to make sure they are included by the single
+// header for non obj-usage
+
+///////////////////////////////////////////////////////////////////////////////
+// This protocol is really only here for (self) documenting purposes, since
+// all its methods are optional.
+@protocol OcFixture
+
+@optional
+
+-(void) setUp;
+-(void) tearDown;
+
+@end
+
+namespace Catch {
+
+    class OcMethod : public SharedImpl<ITestCase> {
+
+    public:
+        OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
+
+        virtual void invoke() const {
+            id obj = [[m_cls alloc] init];
+
+            performOptionalSelector( obj, @selector(setUp)  );
+            performOptionalSelector( obj, m_sel );
+            performOptionalSelector( obj, @selector(tearDown)  );
+
+            arcSafeRelease( obj );
+        }
+    private:
+        virtual ~OcMethod() {}
+
+        Class m_cls;
+        SEL m_sel;
+    };
+
+    namespace Detail{
+
+        inline std::string getAnnotation(   Class cls,
+                                            std::string const& annotationName,
+                                            std::string const& testCaseName ) {
+            NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
+            SEL sel = NSSelectorFromString( selStr );
+            arcSafeRelease( selStr );
+            id value = performOptionalSelector( cls, sel );
+            if( value )
+                return [(NSString*)value UTF8String];
+            return "";
+        }
+    }
+
+    inline size_t registerTestMethods() {
+        size_t noTestMethods = 0;
+        int noClasses = objc_getClassList( NULL, 0 );
+
+        Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
+        objc_getClassList( classes, noClasses );
+
+        for( int c = 0; c < noClasses; c++ ) {
+            Class cls = classes[c];
+            {
+                u_int count;
+                Method* methods = class_copyMethodList( cls, &count );
+                for( u_int m = 0; m < count ; m++ ) {
+                    SEL selector = method_getName(methods[m]);
+                    std::string methodName = sel_getName(selector);
+                    if( startsWith( methodName, "Catch_TestCase_" ) ) {
+                        std::string testCaseName = methodName.substr( 15 );
+                        std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
+                        std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
+                        const char* className = class_getName( cls );
+
+                        getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
+                        noTestMethods++;
+                    }
+                }
+                free(methods);
+            }
+        }
+        return noTestMethods;
+    }
+
+    namespace Matchers {
+        namespace Impl {
+        namespace NSStringMatchers {
+
+            template<typename MatcherT>
+            struct StringHolder : MatcherImpl<MatcherT, NSString*>{
+                StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
+                StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
+                StringHolder() {
+                    arcSafeRelease( m_substr );
+                }
+
+                NSString* m_substr;
+            };
+
+            struct Equals : StringHolder<Equals> {
+                Equals( NSString* substr ) : StringHolder( substr ){}
+
+                virtual bool match( ExpressionType const& str ) const {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str isEqualToString:m_substr];
+                }
+
+                virtual std::string toString() const {
+                    return "equals string: \"" + Catch::toString( m_substr ) + "\"";
+                }
+            };
+
+            struct Contains : StringHolder<Contains> {
+                Contains( NSString* substr ) : StringHolder( substr ){}
+
+                virtual bool match( ExpressionType const& str ) const {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str rangeOfString:m_substr].location != NSNotFound;
+                }
+
+                virtual std::string toString() const {
+                    return "contains string: \"" + Catch::toString( m_substr ) + "\"";
+                }
+            };
+
+            struct StartsWith : StringHolder<StartsWith> {
+                StartsWith( NSString* substr ) : StringHolder( substr ){}
+
+                virtual bool match( ExpressionType const& str ) const {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str rangeOfString:m_substr].location == 0;
+                }
+
+                virtual std::string toString() const {
+                    return "starts with: \"" + Catch::toString( m_substr ) + "\"";
+                }
+            };
+            struct EndsWith : StringHolder<EndsWith> {
+                EndsWith( NSString* substr ) : StringHolder( substr ){}
+
+                virtual bool match( ExpressionType const& str ) const {
+                    return  (str != nil || m_substr == nil ) &&
+                            [str rangeOfString:m_substr].location == [str length] - [m_substr length];
+                }
+
+                virtual std::string toString() const {
+                    return "ends with: \"" + Catch::toString( m_substr ) + "\"";
+                }
+            };
+
+        } // namespace NSStringMatchers
+        } // namespace Impl
+
+        inline Impl::NSStringMatchers::Equals
+            Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
+
+        inline Impl::NSStringMatchers::Contains
+            Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
+
+        inline Impl::NSStringMatchers::StartsWith
+            StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
+
+        inline Impl::NSStringMatchers::EndsWith
+            EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
+
+    } // namespace Matchers
+
+    using namespace Matchers;
+
+} // namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define OC_TEST_CASE( name, desc )\
++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
+{\
+return @ name; \
+}\
++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
+{ \
+return @ desc; \
+} \
+-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
+
+#endif
+
+#ifdef CATCH_CONFIG_RUNNER
+// #included from: internal/catch_impl.hpp
+#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
+
+// Collect all the implementation files together here
+// These are the equivalent of what would usually be cpp files
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
+// #included from: catch_runner.hpp
+#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
+
+// #included from: internal/catch_commandline.hpp
+#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
+
+// #included from: catch_config.hpp
+#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
+
+// #included from: catch_test_spec.h
+#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
+
+// #included from: catch_tags.h
+#define TWOBLUECUBES_CATCH_TAGS_H_INCLUDED
+
+#include <string>
+#include <set>
+#include <map>
+#include <vector>
+
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+    class TagParser {
+    public:
+        virtual ~TagParser();
+
+        void parse( std::string const& str );
+
+    protected:
+        virtual void acceptTag( std::string const& tag ) = 0;
+        virtual void acceptChar( char c ) = 0;
+        virtual void endParse() {}
+
+    private:
+    };
+
+    class TagExtracter : public TagParser {
+    public:
+
+        TagExtracter( std::set<std::string>& tags );
+        virtual ~TagExtracter();
+
+        void parse( std::string& description );
+
+    private:
+        virtual void acceptTag( std::string const& tag );
+        virtual void acceptChar( char c );
+
+        TagExtracter& operator=(TagExtracter const&);
+
+        std::set<std::string>& m_tags;
+        std::string m_remainder;
+    };
+
+    class Tag {
+    public:
+        Tag();
+        Tag( std::string const& name, bool isNegated );
+        std::string getName() const;
+        bool isNegated() const;
+        bool operator ! () const;
+
+    private:
+        std::string m_name;
+        bool m_isNegated;
+    };
+
+    class TagSet {
+        typedef std::map<std::string, Tag> TagMap;
+    public:
+        void add( Tag const& tag );
+        bool empty() const;
+        bool matches( std::set<std::string> const& tags ) const;
+
+    private:
+        TagMap m_tags;
+    };
+
+    class TagExpression {
+    public:
+        bool matches( std::set<std::string> const& tags ) const;
+
+    private:
+        friend class TagExpressionParser;
+
+        std::vector<TagSet> m_tagSets;
+    };
+
+    class TagExpressionParser : public TagParser {
+    public:
+        TagExpressionParser( TagExpression& exp );
+        ~TagExpressionParser();
+
+    private:
+        virtual void acceptTag( std::string const& tag );
+        virtual void acceptChar( char c );
+        virtual void endParse();
+
+        TagExpressionParser& operator=(TagExpressionParser const&);
+
+        bool m_isNegated;
+        TagSet m_currentTagSet;
+        TagExpression& m_exp;
+    };
+
+} // end namespace Catch
+
+#include <string>
+#include <vector>
+
+namespace Catch {
+
+    class TestCase;
+
+    struct IfFilterMatches{ enum DoWhat {
+        AutoDetectBehaviour,
+        IncludeTests,
+        ExcludeTests
+    }; };
+
+    class TestCaseFilter {
+        enum WildcardPosition {
+            NoWildcard = 0,
+            WildcardAtStart = 1,
+            WildcardAtEnd = 2,
+            WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
+        };
+
+    public:
+        TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour );
+
+        IfFilterMatches::DoWhat getFilterType() const;
+        bool shouldInclude( TestCase const& testCase ) const;
+
+    private:
+        bool isMatch( TestCase const& testCase ) const;
+
+        std::string m_stringToMatch;
+        IfFilterMatches::DoWhat m_filterType;
+        WildcardPosition m_wildcardPosition;
+    };
+
+    class TestCaseFilters {
+    public:
+        TestCaseFilters( std::string const& name );
+        std::string getName() const;
+        void addFilter( TestCaseFilter const& filter );
+        void addTags( std::string const& tagPattern );
+        bool shouldInclude( TestCase const& testCase ) const;
+
+    private:
+        std::vector<TagExpression> m_tagExpressions;
+        std::vector<TestCaseFilter> m_inclusionFilters;
+        std::vector<TestCaseFilter> m_exclusionFilters;
+        std::string m_name;
+    };
+
+}
+
+// #included from: catch_stream.h
+#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
+
+#include <streambuf>
+
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+    class Stream {
+    public:
+        Stream();
+        Stream( std::streambuf* _streamBuf, bool _isOwned );
+        void release();
+
+        std::streambuf* streamBuf;
+
+    private:
+        bool isOwned;
+    };
+}
+
+#include <memory>
+#include <vector>
+#include <string>
+#include <iostream>
+
+#ifndef CATCH_CONFIG_CONSOLE_WIDTH
+#define CATCH_CONFIG_CONSOLE_WIDTH 80
+#endif
+
+namespace Catch {
+
+    struct ConfigData {
+
+        ConfigData()
+        :   listTests( false ),
+            listTags( false ),
+            listReporters( false ),
+            listTestNamesOnly( false ),
+            showSuccessfulTests( false ),
+            shouldDebugBreak( false ),
+            noThrow( false ),
+            showHelp( false ),
+            showInvisibles( false ),
+            abortAfter( -1 ),
+            verbosity( Verbosity::Normal ),
+            warnings( WarnAbout::Nothing ),
+            showDurations( ShowDurations::DefaultForReporter )
+        {}
+
+        bool listTests;
+        bool listTags;
+        bool listReporters;
+        bool listTestNamesOnly;
+
+        bool showSuccessfulTests;
+        bool shouldDebugBreak;
+        bool noThrow;
+        bool showHelp;
+        bool showInvisibles;
+
+        int abortAfter;
+
+        Verbosity::Level verbosity;
+        WarnAbout::What warnings;
+        ShowDurations::OrNot showDurations;
+
+        std::string reporterName;
+        std::string outputFilename;
+        std::string name;
+        std::string processName;
+
+        std::vector<std::string> testsOrTags;
+    };
+
+    class Config : public SharedImpl<IConfig> {
+    private:
+        Config( Config const& other );
+        Config& operator = ( Config const& other );
+        virtual void dummy();
+    public:
+
+        Config()
+        :   m_os( std::cout.rdbuf() )
+        {}
+
+        Config( ConfigData const& data )
+        :   m_data( data ),
+            m_os( std::cout.rdbuf() )
+        {
+            if( !data.testsOrTags.empty() ) {
+                std::string groupName;
+                for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
+                    if( i != 0 )
+                        groupName += " ";
+                    groupName += data.testsOrTags[i];
+                }
+                TestCaseFilters filters( groupName );
+                for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
+                    std::string filter = data.testsOrTags[i];
+                    if( startsWith( filter, "[" ) || startsWith( filter, "~[" ) )
+                        filters.addTags( filter );
+                    else
+                        filters.addFilter( TestCaseFilter( filter ) );
+                }
+                m_filterSets.push_back( filters );
+            }
+        }
+
+        virtual ~Config() {
+            m_os.rdbuf( std::cout.rdbuf() );
+            m_stream.release();
+        }
+
+        void setFilename( std::string const& filename ) {
+            m_data.outputFilename = filename;
+        }
+
+        std::string const& getFilename() const {
+            return m_data.outputFilename ;
+        }
+
+        bool listTests() const { return m_data.listTests; }
+        bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
+        bool listTags() const { return m_data.listTags; }
+        bool listReporters() const { return m_data.listReporters; }
+
+        std::string getProcessName() const {
+            return m_data.processName;
+        }
+
+        bool shouldDebugBreak() const {
+            return m_data.shouldDebugBreak;
+        }
+
+        void setStreamBuf( std::streambuf* buf ) {
+            m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
+        }
+
+        void useStream( std::string const& streamName ) {
+            Stream stream = createStream( streamName );
+            setStreamBuf( stream.streamBuf );
+            m_stream.release();
+            m_stream = stream;
+        }
+
+        std::string getReporterName() const { return m_data.reporterName; }
+
+        void addTestSpec( std::string const& testSpec ) {
+            TestCaseFilters filters( testSpec );
+            filters.addFilter( TestCaseFilter( testSpec ) );
+            m_filterSets.push_back( filters );
+        }
+
+        int abortAfter() const {
+            return m_data.abortAfter;
+        }
+
+        std::vector<TestCaseFilters> const& filters() const {
+            return m_filterSets;
+        }
+
+        bool showHelp() const { return m_data.showHelp; }
+        bool showInvisibles() const { return m_data.showInvisibles; }
+
+        // IConfig interface
+        virtual bool allowThrows() const        { return !m_data.noThrow; }
+        virtual std::ostream& stream() const    { return m_os; }
+        virtual std::string name() const        { return m_data.name.empty() ? m_data.processName : m_data.name; }
+        virtual bool includeSuccessfulResults() const   { return m_data.showSuccessfulTests; }
+        virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
+        virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
+
+    private:
+        ConfigData m_data;
+
+        Stream m_stream;
+        mutable std::ostream m_os;
+        std::vector<TestCaseFilters> m_filterSets;
+    };
+
+} // end namespace Catch
+
+// #included from: catch_clara.h
+#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
+
+// Use Catch's value for console width (store Clara's off to the side, if present)
+#ifdef CLARA_CONFIG_CONSOLE_WIDTH
+#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
+#undef CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
+
+// Declare Clara inside the Catch namespace
+#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
+// #included from: ../external/clara.h
+
+// Only use header guard if we are not using an outer namespace
+#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
+
+#ifndef STITCH_CLARA_OPEN_NAMESPACE
+#define TWOBLUECUBES_CLARA_H_INCLUDED
+#define STITCH_CLARA_OPEN_NAMESPACE
+#define STITCH_CLARA_CLOSE_NAMESPACE
+#else
+#define STITCH_CLARA_CLOSE_NAMESPACE }
+#endif
+
+#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
+
+// ----------- #included from tbc_text_format.h -----------
+
+// Only use header guard if we are not using an outer namespace
+#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
+#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+#define TBC_TEXT_FORMAT_H_INCLUDED
+#endif
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+// Use optional outer namespace
+#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
+#endif
+
+namespace Tbc {
+
+#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
+    const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
+#else
+    const unsigned int consoleWidth = 80;
+#endif
+
+    struct TextAttributes {
+        TextAttributes()
+        :   initialIndent( std::string::npos ),
+            indent( 0 ),
+            width( consoleWidth-1 ),
+            tabChar( '\t' )
+        {}
+
+        TextAttributes& setInitialIndent( std::size_t _value )  { initialIndent = _value; return *this; }
+        TextAttributes& setIndent( std::size_t _value )         { indent = _value; return *this; }
+        TextAttributes& setWidth( std::size_t _value )          { width = _value; return *this; }
+        TextAttributes& setTabChar( char _value )               { tabChar = _value; return *this; }
+
+        std::size_t initialIndent;  // indent of first line, or npos
+        std::size_t indent;         // indent of subsequent lines, or all if initialIndent is npos
+        std::size_t width;          // maximum width of text, including indent. Longer text will wrap
+        char tabChar;               // If this char is seen the indent is changed to current pos
+    };
+
+    class Text {
+    public:
+        Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
+        : attr( _attr )
+        {
+            std::string wrappableChars = " [({.,/|\\-";
+            std::size_t indent = _attr.initialIndent != std::string::npos
+                ? _attr.initialIndent
+                : _attr.indent;
+            std::string remainder = _str;
+
+            while( !remainder.empty() ) {
+                if( lines.size() >= 1000 ) {
+                    lines.push_back( "... message truncated due to excessive size" );
+                    return;
+                }
+                std::size_t tabPos = std::string::npos;
+                std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
+                std::size_t pos = remainder.find_first_of( '\n' );
+                if( pos <= width ) {
+                    width = pos;
+                }
+                pos = remainder.find_last_of( _attr.tabChar, width );
+                if( pos != std::string::npos ) {
+                    tabPos = pos;
+                    if( remainder[width] == '\n' )
+                        width--;
+                    remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
+                }
+
+                if( width == remainder.size() ) {
+                    spliceLine( indent, remainder, width );
+                }
+                else if( remainder[width] == '\n' ) {
+                    spliceLine( indent, remainder, width );
+                    if( width <= 1 || remainder.size() != 1 )
+                        remainder = remainder.substr( 1 );
+                    indent = _attr.indent;
+                }
+                else {
+                    pos = remainder.find_last_of( wrappableChars, width );
+                    if( pos != std::string::npos && pos > 0 ) {
+                        spliceLine( indent, remainder, pos );
+                        if( remainder[0] == ' ' )
+                            remainder = remainder.substr( 1 );
+                    }
+                    else {
+                        spliceLine( indent, remainder, width-1 );
+                        lines.back() += "-";
+                    }
+                    if( lines.size() == 1 )
+                        indent = _attr.indent;
+                    if( tabPos != std::string::npos )
+                        indent += tabPos;
+                }
+            }
+        }
+
+        void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
+            lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
+            _remainder = _remainder.substr( _pos );
+        }
+
+        typedef std::vector<std::string>::const_iterator const_iterator;
+
+        const_iterator begin() const { return lines.begin(); }
+        const_iterator end() const { return lines.end(); }
+        std::string const& last() const { return lines.back(); }
+        std::size_t size() const { return lines.size(); }
+        std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
+        std::string toString() const {
+            std::ostringstream oss;
+            oss << *this;
+            return oss.str();
+        }
+
+        inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
+            for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
+                it != itEnd; ++it ) {
+                if( it != _text.begin() )
+                    _stream << "\n";
+                _stream << *it;
+            }
+            return _stream;
+        }
+
+    private:
+        std::string str;
+        TextAttributes attr;
+        std::vector<std::string> lines;
+    };
+
+} // end namespace Tbc
+
+#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+} // end outer namespace
+#endif
+
+#endif // TBC_TEXT_FORMAT_H_INCLUDED
+
+// ----------- end of #include from tbc_text_format.h -----------
+// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h
+
+#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
+
+#include <map>
+#include <algorithm>
+#include <stdexcept>
+#include <memory>
+
+// Use optional outer namespace
+#ifdef STITCH_CLARA_OPEN_NAMESPACE
+STITCH_CLARA_OPEN_NAMESPACE
+#endif
+
+namespace Clara {
+
+    struct UnpositionalTag {};
+
+    extern UnpositionalTag _;
+
+#ifdef CLARA_CONFIG_MAIN
+    UnpositionalTag _;
+#endif
+
+    namespace Detail {
+
+#ifdef CLARA_CONSOLE_WIDTH
+    const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
+#else
+    const unsigned int consoleWidth = 80;
+#endif
+
+        using namespace Tbc;
+
+        inline bool startsWith( std::string const& str, std::string const& prefix ) {
+            return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
+        }
+
+        template<typename T> struct RemoveConstRef{ typedef T type; };
+        template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
+        template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
+        template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
+
+        template<typename T>    struct IsBool       { static const bool value = false; };
+        template<>              struct IsBool<bool> { static const bool value = true; };
+
+        template<typename T>
+        void convertInto( std::string const& _source, T& _dest ) {
+            std::stringstream ss;
+            ss << _source;
+            ss >> _dest;
+            if( ss.fail() )
+                throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
+        }
+        inline void convertInto( std::string const& _source, std::string& _dest ) {
+            _dest = _source;
+        }
+        inline void convertInto( std::string const& _source, bool& _dest ) {
+            std::string sourceLC = _source;
+            std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
+            if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
+                _dest = true;
+            else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
+                _dest = false;
+            else
+                throw std::runtime_error( "Expected a boolean value but did not recognise:\n  '" + _source + "'" );
+        }
+        inline void convertInto( bool _source, bool& _dest ) {
+            _dest = _source;
+        }
+        template<typename T>
+        inline void convertInto( bool, T& ) {
+            throw std::runtime_error( "Invalid conversion" );
+        }
+
+        template<typename ConfigT>
+        struct IArgFunction {
+            virtual ~IArgFunction() {}
+#  ifdef CATCH_CPP11_OR_GREATER
+            IArgFunction()                      = default;
+            IArgFunction( IArgFunction const& ) = default;
+#  endif
+            virtual void set( ConfigT& config, std::string const& value ) const = 0;
+            virtual void setFlag( ConfigT& config ) const = 0;
+            virtual bool takesArg() const = 0;
+            virtual IArgFunction* clone() const = 0;
+        };
+
+        template<typename ConfigT>
+        class BoundArgFunction {
+        public:
+            BoundArgFunction() : functionObj( NULL ) {}
+            BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
+            BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
+            BoundArgFunction& operator = ( BoundArgFunction const& other ) {
+                IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL;
+                delete functionObj;
+                functionObj = newFunctionObj;
+                return *this;
+            }
+            ~BoundArgFunction() { delete functionObj; }
+
+            void set( ConfigT& config, std::string const& value ) const {
+                functionObj->set( config, value );
+            }
+            void setFlag( ConfigT& config ) const {
+                functionObj->setFlag( config );
+            }
+            bool takesArg() const { return functionObj->takesArg(); }
+
+            bool isSet() const {
+                return functionObj != NULL;
+            }
+        private:
+            IArgFunction<ConfigT>* functionObj;
+        };
+
+        template<typename C>
+        struct NullBinder : IArgFunction<C>{
+            virtual void set( C&, std::string const& ) const {}
+            virtual void setFlag( C& ) const {}
+            virtual bool takesArg() const { return true; }
+            virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
+        };
+
+        template<typename C, typename M>
+        struct BoundDataMember : IArgFunction<C>{
+            BoundDataMember( M C::* _member ) : member( _member ) {}
+            virtual void set( C& p, std::string const& stringValue ) const {
+                convertInto( stringValue, p.*member );
+            }
+            virtual void setFlag( C& p ) const {
+                convertInto( true, p.*member );
+            }
+            virtual bool takesArg() const { return !IsBool<M>::value; }
+            virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
+            M C::* member;
+        };
+        template<typename C, typename M>
+        struct BoundUnaryMethod : IArgFunction<C>{
+            BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
+            virtual void set( C& p, std::string const& stringValue ) const {
+                typename RemoveConstRef<M>::type value;
+                convertInto( stringValue, value );
+                (p.*member)( value );
+            }
+            virtual void setFlag( C& p ) const {
+                typename RemoveConstRef<M>::type value;
+                convertInto( true, value );
+                (p.*member)( value );
+            }
+            virtual bool takesArg() const { return !IsBool<M>::value; }
+            virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
+            void (C::*member)( M );
+        };
+        template<typename C>
+        struct BoundNullaryMethod : IArgFunction<C>{
+            BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
+            virtual void set( C& p, std::string const& stringValue ) const {
+                bool value;
+                convertInto( stringValue, value );
+                if( value )
+                    (p.*member)();
+            }
+            virtual void setFlag( C& p ) const {
+                (p.*member)();
+            }
+            virtual bool takesArg() const { return false; }
+            virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
+            void (C::*member)();
+        };
+
+        template<typename C>
+        struct BoundUnaryFunction : IArgFunction<C>{
+            BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
+            virtual void set( C& obj, std::string const& stringValue ) const {
+                bool value;
+                convertInto( stringValue, value );
+                if( value )
+                    function( obj );
+            }
+            virtual void setFlag( C& p ) const {
+                function( p );
+            }
+            virtual bool takesArg() const { return false; }
+            virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
+            void (*function)( C& );
+        };
+
+        template<typename C, typename T>
+        struct BoundBinaryFunction : IArgFunction<C>{
+            BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
+            virtual void set( C& obj, std::string const& stringValue ) const {
+                typename RemoveConstRef<T>::type value;
+                convertInto( stringValue, value );
+                function( obj, value );
+            }
+            virtual void setFlag( C& obj ) const {
+                typename RemoveConstRef<T>::type value;
+                convertInto( true, value );
+                function( obj, value );
+            }
+            virtual bool takesArg() const { return !IsBool<T>::value; }
+            virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
+            void (*function)( C&, T );
+        };
+
+    } // namespace Detail
+
+    struct Parser {
+        Parser() : separators( " \t=:" ) {}
+
+        struct Token {
+            enum Type { Positional, ShortOpt, LongOpt };
+            Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
+            Type type;
+            std::string data;
+        };
+
+        void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
+            const std::string doubleDash = "--";
+            for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
+                parseIntoTokens( argv[i] , tokens);
+        }
+        void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
+            while( !arg.empty() ) {
+                Parser::Token token( Parser::Token::Positional, arg );
+                arg = "";
+                if( token.data[0] == '-' ) {
+                    if( token.data.size() > 1 && token.data[1] == '-' ) {
+                        token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
+                    }
+                    else {
+                        token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
+                        if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
+                            arg = "-" + token.data.substr( 1 );
+                            token.data = token.data.substr( 0, 1 );
+                        }
+                    }
+                }
+                if( token.type != Parser::Token::Positional ) {
+                    std::size_t pos = token.data.find_first_of( separators );
+                    if( pos != std::string::npos ) {
+                        arg = token.data.substr( pos+1 );
+                        token.data = token.data.substr( 0, pos );
+                    }
+                }
+                tokens.push_back( token );
+            }
+        }
+        std::string separators;
+    };
+
+    template<typename ConfigT>
+    struct CommonArgProperties {
+        CommonArgProperties() {}
+        CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
+
+        Detail::BoundArgFunction<ConfigT> boundField;
+        std::string description;
+        std::string detail;
+        std::string placeholder; // Only value if boundField takes an arg
+
+        bool takesArg() const {
+            return !placeholder.empty();
+        }
+        void validate() const {
+            if( !boundField.isSet() )
+                throw std::logic_error( "option not bound" );
+        }
+    };
+    struct OptionArgProperties {
+        std::vector<std::string> shortNames;
+        std::string longName;
+
+        bool hasShortName( std::string const& shortName ) const {
+            return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
+        }
+        bool hasLongName( std::string const& _longName ) const {
+            return _longName == longName;
+        }
+    };
+    struct PositionalArgProperties {
+        PositionalArgProperties() : position( -1 ) {}
+        int position; // -1 means non-positional (floating)
+
+        bool isFixedPositional() const {
+            return position != -1;
+        }
+    };
+
+    template<typename ConfigT>
+    class CommandLine {
+
+        struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
+            Arg() {}
+            Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
+
+            using CommonArgProperties<ConfigT>::placeholder; // !TBD
+
+            std::string dbgName() const {
+                if( !longName.empty() )
+                    return "--" + longName;
+                if( !shortNames.empty() )
+                    return "-" + shortNames[0];
+                return "positional args";
+            }
+            std::string commands() const {
+                std::ostringstream oss;
+                bool first = true;
+                std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
+                for(; it != itEnd; ++it ) {
+                    if( first )
+                        first = false;
+                    else
+                        oss << ", ";
+                    oss << "-" << *it;
+                }
+                if( !longName.empty() ) {
+                    if( !first )
+                        oss << ", ";
+                    oss << "--" << longName;
+                }
+                if( !placeholder.empty() )
+                    oss << " <" << placeholder << ">";
+                return oss.str();
+            }
+        };
+
+        // NOTE: std::auto_ptr is deprecated in c++11/c++0x
+#if defined(__cplusplus) && __cplusplus > 199711L
+        typedef std::unique_ptr<Arg> ArgAutoPtr;
+#else
+        typedef std::auto_ptr<Arg> ArgAutoPtr;
+#endif
+
+        friend void addOptName( Arg& arg, std::string const& optName )
+        {
+            if( optName.empty() )
+                return;
+            if( Detail::startsWith( optName, "--" ) ) {
+                if( !arg.longName.empty() )
+                    throw std::logic_error( "Only one long opt may be specified. '"
+                        + arg.longName
+                        + "' already specified, now attempting to add '"
+                        + optName + "'" );
+                arg.longName = optName.substr( 2 );
+            }
+            else if( Detail::startsWith( optName, "-" ) )
+                arg.shortNames.push_back( optName.substr( 1 ) );
+            else
+                throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
+        }
+        friend void setPositionalArg( Arg& arg, int position )
+        {
+            arg.position = position;
+        }
+
+        class ArgBuilder {
+        public:
+            ArgBuilder( Arg* arg ) : m_arg( arg ) {}
+
+            // Bind a non-boolean data member (requires placeholder string)
+            template<typename C, typename M>
+            void bind( M C::* field, std::string const& placeholder ) {
+                m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
+                m_arg->placeholder = placeholder;
+            }
+            // Bind a boolean data member (no placeholder required)
+            template<typename C>
+            void bind( bool C::* field ) {
+                m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
+            }
+
+            // Bind a method taking a single, non-boolean argument (requires a placeholder string)
+            template<typename C, typename M>
+            void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
+                m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
+                m_arg->placeholder = placeholder;
+            }
+
+            // Bind a method taking a single, boolean argument (no placeholder string required)
+            template<typename C>
+            void bind( void (C::* unaryMethod)( bool ) ) {
+                m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
+            }
+
+            // Bind a method that takes no arguments (will be called if opt is present)
+            template<typename C>
+            void bind( void (C::* nullaryMethod)() ) {
+                m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
+            }
+
+            // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
+            template<typename C>
+            void bind( void (* unaryFunction)( C& ) ) {
+                m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
+            }
+
+            // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
+            template<typename C, typename T>
+            void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
+                m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
+                m_arg->placeholder = placeholder;
+            }
+
+            ArgBuilder& describe( std::string const& description ) {
+                m_arg->description = description;
+                return *this;
+            }
+            ArgBuilder& detail( std::string const& detail ) {
+                m_arg->detail = detail;
+                return *this;
+            }
+
+        protected:
+            Arg* m_arg;
+        };
+
+        class OptBuilder : public ArgBuilder {
+        public:
+            OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
+            OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
+
+            OptBuilder& operator[]( std::string const& optName ) {
+                addOptName( *ArgBuilder::m_arg, optName );
+                return *this;
+            }
+        };
+
+    public:
+
+        CommandLine()
+        :   m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
+            m_highestSpecifiedArgPosition( 0 ),
+            m_throwOnUnrecognisedTokens( false )
+        {}
+        CommandLine( CommandLine const& other )
+        :   m_boundProcessName( other.m_boundProcessName ),
+            m_options ( other.m_options ),
+            m_positionalArgs( other.m_positionalArgs ),
+            m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
+            m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
+        {
+            if( other.m_floatingArg.get() )
+                m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) );
+        }
+
+        CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
+            m_throwOnUnrecognisedTokens = shouldThrow;
+            return *this;
+        }
+
+        OptBuilder operator[]( std::string const& optName ) {
+            m_options.push_back( Arg() );
+            addOptName( m_options.back(), optName );
+            OptBuilder builder( &m_options.back() );
+            return builder;
+        }
+
+        ArgBuilder operator[]( int position ) {
+            m_positionalArgs.insert( std::make_pair( position, Arg() ) );
+            if( position > m_highestSpecifiedArgPosition )
+                m_highestSpecifiedArgPosition = position;
+            setPositionalArg( m_positionalArgs[position], position );
+            ArgBuilder builder( &m_positionalArgs[position] );
+            return builder;
+        }
+
+        // Invoke this with the _ instance
+        ArgBuilder operator[]( UnpositionalTag ) {
+            if( m_floatingArg.get() )
+                throw std::logic_error( "Only one unpositional argument can be added" );
+            m_floatingArg = ArgAutoPtr( new Arg() );
+            ArgBuilder builder( m_floatingArg.get() );
+            return builder;
+        }
+
+        template<typename C, typename M>
+        void bindProcessName( M C::* field ) {
+            m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
+        }
+        template<typename C, typename M>
+        void bindProcessName( void (C::*_unaryMethod)( M ) ) {
+            m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
+        }
+
+        void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
+            typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
+            std::size_t maxWidth = 0;
+            for( it = itBegin; it != itEnd; ++it )
+                maxWidth = (std::max)( maxWidth, it->commands().size() );
+
+            for( it = itBegin; it != itEnd; ++it ) {
+                Detail::Text usage( it->commands(), Detail::TextAttributes()
+                                                        .setWidth( maxWidth+indent )
+                                                        .setIndent( indent ) );
+                Detail::Text desc( it->description, Detail::TextAttributes()
+                                                        .setWidth( width - maxWidth - 3 ) );
+
+                for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
+                    std::string usageCol = i < usage.size() ? usage[i] : "";
+                    os << usageCol;
+
+                    if( i < desc.size() && !desc[i].empty() )
+                        os  << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
+                            << desc[i];
+                    os << "\n";
+                }
+            }
+        }
+        std::string optUsage() const {
+            std::ostringstream oss;
+            optUsage( oss );
+            return oss.str();
+        }
+
+        void argSynopsis( std::ostream& os ) const {
+            for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
+                if( i > 1 )
+                    os << " ";
+                typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
+                if( it != m_positionalArgs.end() )
+                    os << "<" << it->second.placeholder << ">";
+                else if( m_floatingArg.get() )
+                    os << "<" << m_floatingArg->placeholder << ">";
+                else
+                    throw std::logic_error( "non consecutive positional arguments with no floating args" );
+            }
+            // !TBD No indication of mandatory args
+            if( m_floatingArg.get() ) {
+                if( m_highestSpecifiedArgPosition > 1 )
+                    os << " ";
+                os << "[<" << m_floatingArg->placeholder << "> ...]";
+            }
+        }
+        std::string argSynopsis() const {
+            std::ostringstream oss;
+            argSynopsis( oss );
+            return oss.str();
+        }
+
+        void usage( std::ostream& os, std::string const& procName ) const {
+            validate();
+            os << "usage:\n  " << procName << " ";
+            argSynopsis( os );
+            if( !m_options.empty() ) {
+                os << " [options]\n\nwhere options are: \n";
+                optUsage( os, 2 );
+            }
+            os << "\n";
+        }
+        std::string usage( std::string const& procName ) const {
+            std::ostringstream oss;
+            usage( oss, procName );
+            return oss.str();
+        }
+
+        ConfigT parse( int argc, char const * const * argv ) const {
+            ConfigT config;
+            parseInto( argc, argv, config );
+            return config;
+        }
+
+        std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
+            std::string processName = argv[0];
+            std::size_t lastSlash = processName.find_last_of( "/\\" );
+            if( lastSlash != std::string::npos )
+                processName = processName.substr( lastSlash+1 );
+            m_boundProcessName.set( config, processName );
+            std::vector<Parser::Token> tokens;
+            Parser parser;
+            parser.parseIntoTokens( argc, argv, tokens );
+            return populate( tokens, config );
+        }
+
+        std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+            validate();
+            std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
+            unusedTokens = populateFixedArgs( unusedTokens, config );
+            unusedTokens = populateFloatingArgs( unusedTokens, config );
+            return unusedTokens;
+        }
+
+        std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+            std::vector<Parser::Token> unusedTokens;
+            std::vector<std::string> errors;
+            for( std::size_t i = 0; i < tokens.size(); ++i ) {
+                Parser::Token const& token = tokens[i];
+                typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
+                for(; it != itEnd; ++it ) {
+                    Arg const& arg = *it;
+
+                    try {
+                        if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
+                            ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
+                            if( arg.takesArg() ) {
+                                if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
+                                    errors.push_back( "Expected argument to option: " + token.data );
+                                else
+                                    arg.boundField.set( config, tokens[++i].data );
+                            }
+                            else {
+                                arg.boundField.setFlag( config );
+                            }
+                            break;
+                        }
+                    }
+                    catch( std::exception& ex ) {
+                        errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
+                    }
+                }
+                if( it == itEnd ) {
+                    if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
+                        unusedTokens.push_back( token );
+                    else if( m_throwOnUnrecognisedTokens )
+                        errors.push_back( "unrecognised option: " + token.data );
+                }
+            }
+            if( !errors.empty() ) {
+                std::ostringstream oss;
+                for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
+                        it != itEnd;
+                        ++it ) {
+                    if( it != errors.begin() )
+                        oss << "\n";
+                    oss << *it;
+                }
+                throw std::runtime_error( oss.str() );
+            }
+            return unusedTokens;
+        }
+        std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+            std::vector<Parser::Token> unusedTokens;
+            int position = 1;
+            for( std::size_t i = 0; i < tokens.size(); ++i ) {
+                Parser::Token const& token = tokens[i];
+                typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
+                if( it != m_positionalArgs.end() )
+                    it->second.boundField.set( config, token.data );
+                else
+                    unusedTokens.push_back( token );
+                if( token.type == Parser::Token::Positional )
+                    position++;
+            }
+            return unusedTokens;
+        }
+        std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+            if( !m_floatingArg.get() )
+                return tokens;
+            std::vector<Parser::Token> unusedTokens;
+            for( std::size_t i = 0; i < tokens.size(); ++i ) {
+                Parser::Token const& token = tokens[i];
+                if( token.type == Parser::Token::Positional )
+                    m_floatingArg->boundField.set( config, token.data );
+                else
+                    unusedTokens.push_back( token );
+            }
+            return unusedTokens;
+        }
+
+        void validate() const
+        {
+            if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
+                throw std::logic_error( "No options or arguments specified" );
+
+            for( typename std::vector<Arg>::const_iterator  it = m_options.begin(),
+                                                            itEnd = m_options.end();
+                    it != itEnd; ++it )
+                it->validate();
+        }
+
+    private:
+        Detail::BoundArgFunction<ConfigT> m_boundProcessName;
+        std::vector<Arg> m_options;
+        std::map<int, Arg> m_positionalArgs;
+        ArgAutoPtr m_floatingArg;
+        int m_highestSpecifiedArgPosition;
+        bool m_throwOnUnrecognisedTokens;
+    };
+
+} // end namespace Clara
+
+STITCH_CLARA_CLOSE_NAMESPACE
+#undef STITCH_CLARA_OPEN_NAMESPACE
+#undef STITCH_CLARA_CLOSE_NAMESPACE
+
+#endif // TWOBLUECUBES_CLARA_H_INCLUDED
+#undef STITCH_CLARA_OPEN_NAMESPACE
+
+// Restore Clara's value for console width, if present
+#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+
+#include <fstream>
+
+namespace Catch {
+
+    inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
+    inline void abortAfterX( ConfigData& config, int x ) {
+        if( x < 1 )
+            throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
+        config.abortAfter = x;
+    }
+    inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
+
+    inline void addWarning( ConfigData& config, std::string const& _warning ) {
+        if( _warning == "NoAssertions" )
+            config.warnings = (WarnAbout::What)( config.warnings | WarnAbout::NoAssertions );
+        else
+            throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
+
+    }
+    inline void setVerbosity( ConfigData& config, int level ) {
+        // !TBD: accept strings?
+        config.verbosity = (Verbosity::Level)level;
+    }
+    inline void setShowDurations( ConfigData& config, bool _showDurations ) {
+        config.showDurations = _showDurations
+            ? ShowDurations::Always
+            : ShowDurations::Never;
+    }
+    inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
+        std::ifstream f( _filename.c_str() );
+        if( !f.is_open() )
+            throw std::domain_error( "Unable to load input file: " + _filename );
+
+        std::string line;
+        while( std::getline( f, line ) ) {
+            line = trim(line);
+            if( !line.empty() && !startsWith( line, "#" ) )
+                addTestOrTags( config, line );
+        }
+    }
+
+    inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
+
+        using namespace Clara;
+        CommandLine<ConfigData> cli;
+
+        cli.bindProcessName( &ConfigData::processName );
+
+        cli["-?"]["-h"]["--help"]
+            .describe( "display usage information" )
+            .bind( &ConfigData::showHelp );
+
+        cli["-l"]["--list-tests"]
+            .describe( "list all/matching test cases" )
+            .bind( &ConfigData::listTests );
+
+        cli["-t"]["--list-tags"]
+            .describe( "list all/matching tags" )
+            .bind( &ConfigData::listTags );
+
+        cli["-s"]["--success"]
+            .describe( "include successful tests in output" )
+            .bind( &ConfigData::showSuccessfulTests );
+
+        cli["-b"]["--break"]
+            .describe( "break into debugger on failure" )
+            .bind( &ConfigData::shouldDebugBreak );
+
+        cli["-e"]["--nothrow"]
+            .describe( "skip exception tests" )
+            .bind( &ConfigData::noThrow );
+
+        cli["-i"]["--invisibles"]
+            .describe( "show invisibles (tabs, newlines)" )
+            .bind( &ConfigData::showInvisibles );
+
+        cli["-o"]["--out"]
+            .describe( "output filename" )
+            .bind( &ConfigData::outputFilename, "filename" );
+
+        cli["-r"]["--reporter"]
+//            .placeholder( "name[:filename]" )
+            .describe( "reporter to use (defaults to console)" )
+            .bind( &ConfigData::reporterName, "name" );
+
+        cli["-n"]["--name"]
+            .describe( "suite name" )
+            .bind( &ConfigData::name, "name" );
+
+        cli["-a"]["--abort"]
+            .describe( "abort at first failure" )
+            .bind( &abortAfterFirst );
+
+        cli["-x"]["--abortx"]
+            .describe( "abort after x failures" )
+            .bind( &abortAfterX, "no. failures" );
+
+        cli["-w"]["--warn"]
+            .describe( "enable warnings" )
+            .bind( &addWarning, "warning name" );
+
+// - needs updating if reinstated
+//        cli.into( &setVerbosity )
+//            .describe( "level of verbosity (0=no output)" )
+//            .shortOpt( "v")
+//            .longOpt( "verbosity" )
+//            .placeholder( "level" );
+
+        cli[_]
+            .describe( "which test or tests to use" )
+            .bind( &addTestOrTags, "test name, pattern or tags" );
+
+        cli["-d"]["--durations"]
+            .describe( "show test durations" )
+            .bind( &setShowDurations, "yes/no" );
+
+        cli["-f"]["--input-file"]
+            .describe( "load test names to run from a file" )
+            .bind( &loadTestNamesFromFile, "filename" );
+
+        // Less common commands which don't have a short form
+        cli["--list-test-names-only"]
+            .describe( "list all/matching test cases names only" )
+            .bind( &ConfigData::listTestNamesOnly );
+
+        cli["--list-reporters"]
+            .describe( "list all reporters" )
+            .bind( &ConfigData::listReporters );
+
+        return cli;
+    }
+
+} // end namespace Catch
+
+// #included from: internal/catch_list.hpp
+#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
+
+// #included from: catch_text.h
+#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
+
+#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
+
+#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
+// #included from: ../external/tbc_text_format.h
+// Only use header guard if we are not using an outer namespace
+#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
+#  ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#   define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#  endif
+# else
+#  define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
+# endif
+#endif
+#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#include <string>
+#include <vector>
+#include <sstream>
+
+// Use optional outer namespace
+#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
+#endif
+
+namespace Tbc {
+
+#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
+    const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
+#else
+    const unsigned int consoleWidth = 80;
+#endif
+
+    struct TextAttributes {
+        TextAttributes()
+        :   initialIndent( std::string::npos ),
+            indent( 0 ),
+            width( consoleWidth-1 ),
+            tabChar( '\t' )
+        {}
+
+        TextAttributes& setInitialIndent( std::size_t _value )  { initialIndent = _value; return *this; }
+        TextAttributes& setIndent( std::size_t _value )         { indent = _value; return *this; }
+        TextAttributes& setWidth( std::size_t _value )          { width = _value; return *this; }
+        TextAttributes& setTabChar( char _value )               { tabChar = _value; return *this; }
+
+        std::size_t initialIndent;  // indent of first line, or npos
+        std::size_t indent;         // indent of subsequent lines, or all if initialIndent is npos
+        std::size_t width;          // maximum width of text, including indent. Longer text will wrap
+        char tabChar;               // If this char is seen the indent is changed to current pos
+    };
+
+    class Text {
+    public:
+        Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
+        : attr( _attr )
+        {
+            std::string wrappableChars = " [({.,/|\\-";
+            std::size_t indent = _attr.initialIndent != std::string::npos
+                ? _attr.initialIndent
+                : _attr.indent;
+            std::string remainder = _str;
+
+            while( !remainder.empty() ) {
+                if( lines.size() >= 1000 ) {
+                    lines.push_back( "... message truncated due to excessive size" );
+                    return;
+                }
+                std::size_t tabPos = std::string::npos;
+                std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
+                std::size_t pos = remainder.find_first_of( '\n' );
+                if( pos <= width ) {
+                    width = pos;
+                }
+                pos = remainder.find_last_of( _attr.tabChar, width );
+                if( pos != std::string::npos ) {
+                    tabPos = pos;
+                    if( remainder[width] == '\n' )
+                        width--;
+                    remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
+                }
+
+                if( width == remainder.size() ) {
+                    spliceLine( indent, remainder, width );
+                }
+                else if( remainder[width] == '\n' ) {
+                    spliceLine( indent, remainder, width );
+                    if( width <= 1 || remainder.size() != 1 )
+                        remainder = remainder.substr( 1 );
+                    indent = _attr.indent;
+                }
+                else {
+                    pos = remainder.find_last_of( wrappableChars, width );
+                    if( pos != std::string::npos && pos > 0 ) {
+                        spliceLine( indent, remainder, pos );
+                        if( remainder[0] == ' ' )
+                            remainder = remainder.substr( 1 );
+                    }
+                    else {
+                        spliceLine( indent, remainder, width-1 );
+                        lines.back() += "-";
+                    }
+                    if( lines.size() == 1 )
+                        indent = _attr.indent;
+                    if( tabPos != std::string::npos )
+                        indent += tabPos;
+                }
+            }
+        }
+
+        void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
+            lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
+            _remainder = _remainder.substr( _pos );
+        }
+
+        typedef std::vector<std::string>::const_iterator const_iterator;
+
+        const_iterator begin() const { return lines.begin(); }
+        const_iterator end() const { return lines.end(); }
+        std::string const& last() const { return lines.back(); }
+        std::size_t size() const { return lines.size(); }
+        std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
+        std::string toString() const {
+            std::ostringstream oss;
+            oss << *this;
+            return oss.str();
+        }
+
+        inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
+            for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
+                it != itEnd; ++it ) {
+                if( it != _text.begin() )
+                    _stream << "\n";
+                _stream << *it;
+            }
+            return _stream;
+        }
+
+    private:
+        std::string str;
+        TextAttributes attr;
+        std::vector<std::string> lines;
+    };
+
+} // end namespace Tbc
+
+#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+} // end outer namespace
+#endif
+
+#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+
+namespace Catch {
+    using Tbc::Text;
+    using Tbc::TextAttributes;
+}
+
+// #included from: catch_console_colour.hpp
+#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
+
+namespace Catch {
+
+    namespace Detail {
+        struct IColourImpl;
+    }
+
+    struct Colour {
+        enum Code {
+            None = 0,
+
+            White,
+            Red,
+            Green,
+            Blue,
+            Cyan,
+            Yellow,
+            Grey,
+
+            Bright = 0x10,
+
+            BrightRed = Bright | Red,
+            BrightGreen = Bright | Green,
+            LightGrey = Bright | Grey,
+            BrightWhite = Bright | White,
+
+            // By intention
+            FileName = LightGrey,
+            ResultError = BrightRed,
+            ResultSuccess = BrightGreen,
+
+            Error = BrightRed,
+            Success = Green,
+
+            OriginalExpression = Cyan,
+            ReconstructedExpression = Yellow,
+
+            SecondaryText = LightGrey,
+            Headers = White
+        };
+
+        // Use constructed object for RAII guard
+        Colour( Code _colourCode );
+        ~Colour();
+
+        // Use static method for one-shot changes
+        static void use( Code _colourCode );
+
+    private:
+        static Detail::IColourImpl* impl();
+    };
+
+} // end namespace Catch
+
+// #included from: catch_interfaces_reporter.h
+#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
+
+// #included from: catch_option.hpp
+#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
+
+namespace Catch {
+
+    // An optional type
+    template<typename T>
+    class Option {
+    public:
+        Option() : nullableValue( NULL ) {}
+        Option( T const& _value )
+        : nullableValue( new( storage ) T( _value ) )
+        {}
+        Option( Option const& _other )
+        : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
+        {}
+
+        ~Option() {
+            reset();
+        }
+
+        Option& operator= ( Option const& _other ) {
+            if( &_other != this ) {
+                reset();
+                if( _other )
+                    nullableValue = new( storage ) T( *_other );
+            }
+            return *this;
+        }
+        Option& operator = ( T const& _value ) {
+            reset();
+            nullableValue = new( storage ) T( _value );
+            return *this;
+        }
+
+        void reset() {
+            if( nullableValue )
+                nullableValue->~T();
+            nullableValue = NULL;
+        }
+
+        T& operator*() { return *nullableValue; }
+        T const& operator*() const { return *nullableValue; }
+        T* operator->() { return nullableValue; }
+        const T* operator->() const { return nullableValue; }
+
+        T valueOr( T const& defaultValue ) const {
+            return nullableValue ? *nullableValue : defaultValue;
+        }
+
+        bool some() const { return nullableValue != NULL; }
+        bool none() const { return nullableValue == NULL; }
+
+        bool operator !() const { return nullableValue == NULL; }
+        operator SafeBool::type() const {
+            return SafeBool::makeSafe( some() );
+        }
+
+    private:
+        T* nullableValue;
+        char storage[sizeof(T)];
+    };
+
+} // end namespace Catch
+
+#include <string>
+#include <ostream>
+#include <map>
+#include <assert.h>
+
+namespace Catch
+{
+    struct ReporterConfig {
+        explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
+        :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
+
+        ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
+        :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
+
+        std::ostream& stream() const    { return *m_stream; }
+        Ptr<IConfig> fullConfig() const { return m_fullConfig; }
+
+    private:
+        std::ostream* m_stream;
+        Ptr<IConfig> m_fullConfig;
+    };
+
+    struct ReporterPreferences {
+        ReporterPreferences()
+        : shouldRedirectStdOut( false )
+        {}
+
+        bool shouldRedirectStdOut;
+    };
+
+    template<typename T>
+    struct LazyStat : Option<T> {
+        LazyStat() : used( false ) {}
+        LazyStat& operator=( T const& _value ) {
+            Option<T>::operator=( _value );
+            used = false;
+            return *this;
+        }
+        void reset() {
+            Option<T>::reset();
+            used = false;
+        }
+        bool used;
+    };
+
+    struct TestRunInfo {
+        TestRunInfo( std::string const& _name ) : name( _name ) {}
+        std::string name;
+    };
+    struct GroupInfo {
+        GroupInfo(  std::string const& _name,
+                    std::size_t _groupIndex,
+                    std::size_t _groupsCount )
+        :   name( _name ),
+            groupIndex( _groupIndex ),
+            groupsCounts( _groupsCount )
+        {}
+
+        std::string name;
+        std::size_t groupIndex;
+        std::size_t groupsCounts;
+    };
+
+    struct AssertionStats {
+        AssertionStats( AssertionResult const& _assertionResult,
+                        std::vector<MessageInfo> const& _infoMessages,
+                        Totals const& _totals )
+        :   assertionResult( _assertionResult ),
+            infoMessages( _infoMessages ),
+            totals( _totals )
+        {
+            if( assertionResult.hasMessage() ) {
+                // Copy message into messages list.
+                // !TBD This should have been done earlier, somewhere
+                MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
+                builder << assertionResult.getMessage();
+                builder.m_info.message = builder.m_stream.str();
+
+                infoMessages.push_back( builder.m_info );
+            }
+        }
+        virtual ~AssertionStats();
+
+#  ifdef CATCH_CPP11_OR_GREATER
+        AssertionStats( AssertionStats const& )              = default;
+        AssertionStats( AssertionStats && )                  = default;
+        AssertionStats& operator = ( AssertionStats const& ) = default;
+        AssertionStats& operator = ( AssertionStats && )     = default;
+#  endif
+
+        AssertionResult assertionResult;
+        std::vector<MessageInfo> infoMessages;
+        Totals totals;
+    };
+
+    struct SectionStats {
+        SectionStats(   SectionInfo const& _sectionInfo,
+                        Counts const& _assertions,
+                        double _durationInSeconds,
+                        bool _missingAssertions )
+        :   sectionInfo( _sectionInfo ),
+            assertions( _assertions ),
+            durationInSeconds( _durationInSeconds ),
+            missingAssertions( _missingAssertions )
+        {}
+        virtual ~SectionStats();
+#  ifdef CATCH_CPP11_OR_GREATER
+        SectionStats( SectionStats const& )              = default;
+        SectionStats( SectionStats && )                  = default;
+        SectionStats& operator = ( SectionStats const& ) = default;
+        SectionStats& operator = ( SectionStats && )     = default;
+#  endif
+
+        SectionInfo sectionInfo;
+        Counts assertions;
+        double durationInSeconds;
+        bool missingAssertions;
+    };
+
+    struct TestCaseStats {
+        TestCaseStats(  TestCaseInfo const& _testInfo,
+                        Totals const& _totals,
+                        std::string const& _stdOut,
+                        std::string const& _stdErr,
+                        bool _aborting )
+        : testInfo( _testInfo ),
+            totals( _totals ),
+            stdOut( _stdOut ),
+            stdErr( _stdErr ),
+            aborting( _aborting )
+        {}
+        virtual ~TestCaseStats();
+
+#  ifdef CATCH_CPP11_OR_GREATER
+        TestCaseStats( TestCaseStats const& )              = default;
+        TestCaseStats( TestCaseStats && )                  = default;
+        TestCaseStats& operator = ( TestCaseStats const& ) = default;
+        TestCaseStats& operator = ( TestCaseStats && )     = default;
+#  endif
+
+        TestCaseInfo testInfo;
+        Totals totals;
+        std::string stdOut;
+        std::string stdErr;
+        bool aborting;
+    };
+
+    struct TestGroupStats {
+        TestGroupStats( GroupInfo const& _groupInfo,
+                        Totals const& _totals,
+                        bool _aborting )
+        :   groupInfo( _groupInfo ),
+            totals( _totals ),
+            aborting( _aborting )
+        {}
+        TestGroupStats( GroupInfo const& _groupInfo )
+        :   groupInfo( _groupInfo ),
+            aborting( false )
+        {}
+        virtual ~TestGroupStats();
+
+#  ifdef CATCH_CPP11_OR_GREATER
+        TestGroupStats( TestGroupStats const& )              = default;
+        TestGroupStats( TestGroupStats && )                  = default;
+        TestGroupStats& operator = ( TestGroupStats const& ) = default;
+        TestGroupStats& operator = ( TestGroupStats && )     = default;
+#  endif
+
+        GroupInfo groupInfo;
+        Totals totals;
+        bool aborting;
+    };
+
+    struct TestRunStats {
+        TestRunStats(   TestRunInfo const& _runInfo,
+                        Totals const& _totals,
+                        bool _aborting )
+        :   runInfo( _runInfo ),
+            totals( _totals ),
+            aborting( _aborting )
+        {}
+        virtual ~TestRunStats();
+
+#  ifndef CATCH_CPP11_OR_GREATER
+        TestRunStats( TestRunStats const& _other )
+        :   runInfo( _other.runInfo ),
+            totals( _other.totals ),
+            aborting( _other.aborting )
+        {}
+#  else
+        TestRunStats( TestRunStats const& )              = default;
+        TestRunStats( TestRunStats && )                  = default;
+        TestRunStats& operator = ( TestRunStats const& ) = default;
+        TestRunStats& operator = ( TestRunStats && )     = default;
+#  endif
+
+        TestRunInfo runInfo;
+        Totals totals;
+        bool aborting;
+    };
+
+    struct IStreamingReporter : IShared {
+        virtual ~IStreamingReporter();
+
+        // Implementing class must also provide the following static method:
+        // static std::string getDescription();
+
+        virtual ReporterPreferences getPreferences() const = 0;
+
+        virtual void noMatchingTestCases( std::string const& spec ) = 0;
+
+        virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
+        virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
+
+        virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
+        virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
+
+        virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
+
+        virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
+        virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
+        virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
+    };
+
+    struct IReporterFactory {
+        virtual ~IReporterFactory();
+        virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
+        virtual std::string getDescription() const = 0;
+    };
+
+    struct IReporterRegistry {
+        typedef std::map<std::string, IReporterFactory*> FactoryMap;
+
+        virtual ~IReporterRegistry();
+        virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
+        virtual FactoryMap const& getFactories() const = 0;
+    };
+
+}
+
+#include <limits>
+#include <algorithm>
+
+namespace Catch {
+
+    inline std::size_t listTests( Config const& config ) {
+        if( config.filters().empty() )
+            std::cout << "All available test cases:\n";
+        else
+            std::cout << "Matching test cases:\n";
+
+        std::size_t matchedTests = 0;
+        TextAttributes nameAttr, tagsAttr;
+        nameAttr.setInitialIndent( 2 ).setIndent( 4 );
+        tagsAttr.setIndent( 6 );
+
+        std::vector<TestCase> matchedTestCases;
+        getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases );
+        for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+                it != itEnd;
+                ++it ) {
+            matchedTests++;
+            TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
+            Colour::Code colour = testCaseInfo.isHidden
+                ? Colour::SecondaryText
+                : Colour::None;
+            Colour colourGuard( colour );
+
+            std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl;
+            if( !testCaseInfo.tags.empty() )
+                std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
+        }
+
+        if( config.filters().empty() )
+            std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
+        else
+            std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
+        return matchedTests;
+    }
+
+    inline std::size_t listTestsNamesOnly( Config const& config ) {
+        std::size_t matchedTests = 0;
+        std::vector<TestCase> matchedTestCases;
+        getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases );
+        for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+                it != itEnd;
+                ++it ) {
+            matchedTests++;
+            TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
+            std::cout << testCaseInfo.name << std::endl;
+        }
+        return matchedTests;
+    }
+
+    inline std::size_t listTags( Config const& config ) {
+        if( config.filters().empty() )
+            std::cout << "All available tags:\n";
+        else
+            std::cout << "Matching tags:\n";
+
+        std::map<std::string, int> tagCounts;
+
+        std::vector<TestCase> matchedTestCases;
+        getRegistryHub().getTestCaseRegistry().getFilteredTests( config, matchedTestCases );
+        for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+                it != itEnd;
+                ++it ) {
+            for( std::set<std::string>::const_iterator  tagIt = it->getTestCaseInfo().tags.begin(),
+                                                        tagItEnd = it->getTestCaseInfo().tags.end();
+                    tagIt != tagItEnd;
+                    ++tagIt ) {
+                std::string tagName = *tagIt;
+                std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
+                if( countIt == tagCounts.end() )
+                    tagCounts.insert( std::make_pair( tagName, 1 ) );
+                else
+                    countIt->second++;
+            }
+        }
+
+        for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(),
+                                                        countItEnd = tagCounts.end();
+                countIt != countItEnd;
+                ++countIt ) {
+            std::ostringstream oss;
+            oss << "  " << countIt->second << "  ";
+            Text wrapper( "[" + countIt->first + "]", TextAttributes()
+                                                        .setInitialIndent( 0 )
+                                                        .setIndent( oss.str().size() )
+                                                        .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
+            std::cout << oss.str() << wrapper << "\n";
+        }
+        std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
+        return tagCounts.size();
+    }
+
+    inline std::size_t listReporters( Config const& /*config*/ ) {
+        std::cout << "Available reports:\n";
+        IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
+        IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
+        std::size_t maxNameLen = 0;
+        for(it = itBegin; it != itEnd; ++it )
+            maxNameLen = (std::max)( maxNameLen, it->first.size() );
+
+        for(it = itBegin; it != itEnd; ++it ) {
+            Text wrapper( it->second->getDescription(), TextAttributes()
+                                                        .setInitialIndent( 0 )
+                                                        .setIndent( 7+maxNameLen )
+                                                        .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
+            std::cout << "  "
+                    << it->first
+                    << ":"
+                    << std::string( maxNameLen - it->first.size() + 2, ' ' )
+                    << wrapper << "\n";
+        }
+        std::cout << std::endl;
+        return factories.size();
+    }
+
+    inline Option<std::size_t> list( Config const& config ) {
+        Option<std::size_t> listedCount;
+        if( config.listTests() )
+            listedCount = listedCount.valueOr(0) + listTests( config );
+        if( config.listTestNamesOnly() )
+            listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
+        if( config.listTags() )
+            listedCount = listedCount.valueOr(0) + listTags( config );
+        if( config.listReporters() )
+            listedCount = listedCount.valueOr(0) + listReporters( config );
+        return listedCount;
+    }
+
+} // end namespace Catch
+
+// #included from: internal/catch_runner_impl.hpp
+#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
+
+// #included from: catch_test_case_tracker.hpp
+#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
+
+#include <map>
+#include <string>
+#include <assert.h>
+
+namespace Catch {
+namespace SectionTracking {
+
+    class TrackedSection {
+
+        typedef std::map<std::string, TrackedSection> TrackedSections;
+
+    public:
+        enum RunState {
+            NotStarted,
+            Executing,
+            ExecutingChildren,
+            Completed
+        };
+
+        TrackedSection( std::string const& name, TrackedSection* parent )
+        :   m_name( name ), m_runState( NotStarted ), m_parent( parent )
+        {}
+
+        RunState runState() const { return m_runState; }
+
+        TrackedSection* findChild( std::string const& childName ) {
+            TrackedSections::iterator it = m_children.find( childName );
+            return it != m_children.end()
+                ? &it->second
+                : NULL;
+        }
+        TrackedSection* acquireChild( std::string const& childName ) {
+            if( TrackedSection* child = findChild( childName ) )
+                return child;
+            m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
+            return findChild( childName );
+        }
+        void enter() {
+            if( m_runState == NotStarted )
+                m_runState = Executing;
+        }
+        void leave() {
+            for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
+                    it != itEnd;
+                    ++it )
+                if( it->second.runState() != Completed ) {
+                    m_runState = ExecutingChildren;
+                    return;
+                }
+            m_runState = Completed;
+        }
+        TrackedSection* getParent() {
+            return m_parent;
+        }
+        bool hasChildren() const {
+            return !m_children.empty();
+        }
+
+    private:
+        std::string m_name;
+        RunState m_runState;
+        TrackedSections m_children;
+        TrackedSection* m_parent;
+
+    };
+
+    class TestCaseTracker {
+    public:
+        TestCaseTracker( std::string const& testCaseName )
+        :   m_testCase( testCaseName, NULL ),
+            m_currentSection( &m_testCase ),
+            m_completedASectionThisRun( false )
+        {}
+
+        bool enterSection( std::string const& name ) {
+            TrackedSection* child = m_currentSection->acquireChild( name );
+            if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
+                return false;
+
+            m_currentSection = child;
+            m_currentSection->enter();
+            return true;
+        }
+        void leaveSection() {
+            m_currentSection->leave();
+            m_currentSection = m_currentSection->getParent();
+            assert( m_currentSection != NULL );
+            m_completedASectionThisRun = true;
+        }
+
+        bool currentSectionHasChildren() const {
+            return m_currentSection->hasChildren();
+        }
+        bool isCompleted() const {
+            return m_testCase.runState() == TrackedSection::Completed;
+        }
+
+        class Guard {
+        public:
+            Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
+                m_tracker.enterTestCase();
+            }
+            ~Guard() {
+                m_tracker.leaveTestCase();
+            }
+        private:
+            Guard( Guard const& );
+            void operator = ( Guard const& );
+            TestCaseTracker& m_tracker;
+        };
+
+    private:
+        void enterTestCase() {
+            m_currentSection = &m_testCase;
+            m_completedASectionThisRun = false;
+            m_testCase.enter();
+        }
+        void leaveTestCase() {
+            m_testCase.leave();
+        }
+
+        TrackedSection m_testCase;
+        TrackedSection* m_currentSection;
+        bool m_completedASectionThisRun;
+    };
+
+} // namespace SectionTracking
+
+using SectionTracking::TestCaseTracker;
+
+} // namespace Catch
+
+#include <set>
+#include <string>
+
+namespace Catch {
+
+    class StreamRedirect {
+
+    public:
+        StreamRedirect( std::ostream& stream, std::string& targetString )
+        :   m_stream( stream ),
+            m_prevBuf( stream.rdbuf() ),
+            m_targetString( targetString )
+        {
+            stream.rdbuf( m_oss.rdbuf() );
+        }
+
+        ~StreamRedirect() {
+            m_targetString += m_oss.str();
+            m_stream.rdbuf( m_prevBuf );
+        }
+
+    private:
+        std::ostream& m_stream;
+        std::streambuf* m_prevBuf;
+        std::ostringstream m_oss;
+        std::string& m_targetString;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    class RunContext : public IResultCapture, public IRunner {
+
+        RunContext( RunContext const& );
+        void operator =( RunContext const& );
+
+    public:
+
+        explicit RunContext( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> const& reporter )
+        :   m_runInfo( config->name() ),
+            m_context( getCurrentMutableContext() ),
+            m_activeTestCase( NULL ),
+            m_config( config ),
+            m_reporter( reporter ),
+            m_prevRunner( &m_context.getRunner() ),
+            m_prevResultCapture( &m_context.getResultCapture() ),
+            m_prevConfig( m_context.getConfig() )
+        {
+            m_context.setRunner( this );
+            m_context.setConfig( m_config );
+            m_context.setResultCapture( this );
+            m_reporter->testRunStarting( m_runInfo );
+        }
+
+        virtual ~RunContext() {
+            m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
+            m_context.setRunner( m_prevRunner );
+            m_context.setConfig( NULL );
+            m_context.setResultCapture( m_prevResultCapture );
+            m_context.setConfig( m_prevConfig );
+        }
+
+        void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
+            m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
+        }
+        void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
+            m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
+        }
+
+        Totals runTest( TestCase const& testCase ) {
+            Totals prevTotals = m_totals;
+
+            std::string redirectedCout;
+            std::string redirectedCerr;
+
+            TestCaseInfo testInfo = testCase.getTestCaseInfo();
+
+            m_reporter->testCaseStarting( testInfo );
+
+            m_activeTestCase = &testCase;
+            m_testCaseTracker = TestCaseTracker( testInfo.name );
+
+            do {
+                do {
+                    runCurrentTest( redirectedCout, redirectedCerr );
+                }
+                while( !m_testCaseTracker->isCompleted() && !aborting() );
+            }
+            while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
+
+            Totals deltaTotals = m_totals.delta( prevTotals );
+            m_totals.testCases += deltaTotals.testCases;
+            m_reporter->testCaseEnded( TestCaseStats(   testInfo,
+                                                        deltaTotals,
+                                                        redirectedCout,
+                                                        redirectedCerr,
+                                                        aborting() ) );
+
+            m_activeTestCase = NULL;
+            m_testCaseTracker.reset();
+
+            return deltaTotals;
+        }
+
+        Ptr<IConfig const> config() const {
+            return m_config;
+        }
+
+    private: // IResultCapture
+
+        virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) {
+            m_lastAssertionInfo = assertionInfo;
+            return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) );
+        }
+
+        virtual void assertionEnded( AssertionResult const& result ) {
+            if( result.getResultType() == ResultWas::Ok ) {
+                m_totals.assertions.passed++;
+            }
+            else if( !result.isOk() ) {
+                m_totals.assertions.failed++;
+            }
+
+            if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
+                m_messages.clear();
+
+            // Reset working state
+            m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
+        }
+
+        virtual bool sectionStarted (
+            SectionInfo const& sectionInfo,
+            Counts& assertions
+        )
+        {
+            std::ostringstream oss;
+            oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
+
+            if( !m_testCaseTracker->enterSection( oss.str() ) )
+                return false;
+
+            m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
+
+            m_reporter->sectionStarting( sectionInfo );
+
+            assertions = m_totals.assertions;
+
+            return true;
+        }
+        bool testForMissingAssertions( Counts& assertions ) {
+            if( assertions.total() != 0 ||
+                    !m_config->warnAboutMissingAssertions() ||
+                    m_testCaseTracker->currentSectionHasChildren() )
+                return false;
+            m_totals.assertions.failed++;
+            assertions.failed++;
+            return true;
+        }
+
+        virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
+            if( std::uncaught_exception() ) {
+                m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
+                return;
+            }
+
+            Counts assertions = m_totals.assertions - prevAssertions;
+            bool missingAssertions = testForMissingAssertions( assertions );
+
+            m_testCaseTracker->leaveSection();
+
+            m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
+            m_messages.clear();
+        }
+
+        virtual void pushScopedMessage( MessageInfo const& message ) {
+            m_messages.push_back( message );
+        }
+
+        virtual void popScopedMessage( MessageInfo const& message ) {
+            m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
+        }
+
+        virtual bool shouldDebugBreak() const {
+            return m_config->shouldDebugBreak();
+        }
+
+        virtual std::string getCurrentTestName() const {
+            return m_activeTestCase
+                ? m_activeTestCase->getTestCaseInfo().name
+                : "";
+        }
+
+        virtual const AssertionResult* getLastResult() const {
+            return &m_lastResult;
+        }
+
+    public:
+        // !TBD We need to do this another way!
+        bool aborting() const {
+            return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
+        }
+
+    private:
+
+        ResultAction::Value actOnCurrentResult( AssertionResult const& result ) {
+            m_lastResult = result;
+            assertionEnded( m_lastResult );
+
+            ResultAction::Value action = ResultAction::None;
+
+            if( !m_lastResult.isOk() ) {
+                action = ResultAction::Failed;
+                if( shouldDebugBreak() )
+                    action = (ResultAction::Value)( action | ResultAction::Debug );
+                if( aborting() )
+                    action = (ResultAction::Value)( action | ResultAction::Abort );
+            }
+            return action;
+        }
+
+        void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
+            TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
+            SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
+            m_reporter->sectionStarting( testCaseSection );
+            Counts prevAssertions = m_totals.assertions;
+            double duration = 0;
+            try {
+                m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
+                TestCaseTracker::Guard guard( *m_testCaseTracker );
+
+                Timer timer;
+                timer.start();
+                if( m_reporter->getPreferences().shouldRedirectStdOut ) {
+                    StreamRedirect coutRedir( std::cout, redirectedCout );
+                    StreamRedirect cerrRedir( std::cerr, redirectedCerr );
+                    m_activeTestCase->invoke();
+                }
+                else {
+                    m_activeTestCase->invoke();
+                }
+                duration = timer.getElapsedSeconds();
+            }
+            catch( TestFailureException& ) {
+                // This just means the test was aborted due to failure
+            }
+            catch(...) {
+                ExpressionResultBuilder exResult( ResultWas::ThrewException );
+                exResult << translateActiveException();
+                actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo )  );
+            }
+            // If sections ended prematurely due to an exception we stored their
+            // infos here so we can tear them down outside the unwind process.
+            for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
+                        itEnd = m_unfinishedSections.rend();
+                    it != itEnd;
+                    ++it )
+                sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
+            m_unfinishedSections.clear();
+            m_messages.clear();
+
+            Counts assertions = m_totals.assertions - prevAssertions;
+            bool missingAssertions = testForMissingAssertions( assertions );
+
+            SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
+            m_reporter->sectionEnded( testCaseSectionStats );
+        }
+
+    private:
+        struct UnfinishedSections {
+            UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
+            : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
+            {}
+
+            SectionInfo info;
+            Counts prevAssertions;
+            double durationInSeconds;
+        };
+
+        TestRunInfo m_runInfo;
+        IMutableContext& m_context;
+        TestCase const* m_activeTestCase;
+        Option<TestCaseTracker> m_testCaseTracker;
+        AssertionResult m_lastResult;
+
+        Ptr<IConfig const> m_config;
+        Totals m_totals;
+        Ptr<IStreamingReporter> m_reporter;
+        std::vector<MessageInfo> m_messages;
+        IRunner* m_prevRunner;
+        IResultCapture* m_prevResultCapture;
+        Ptr<IConfig const> m_prevConfig;
+        AssertionInfo m_lastAssertionInfo;
+        std::vector<UnfinishedSections> m_unfinishedSections;
+    };
+
+} // end namespace Catch
+
+// #included from: internal/catch_version.h
+#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
+
+namespace Catch {
+
+    // Versioning information
+    struct Version {
+        Version(    unsigned int _majorVersion,
+                    unsigned int _minorVersion,
+                    unsigned int _buildNumber,
+                    char const* const _branchName )
+        :   majorVersion( _majorVersion ),
+            minorVersion( _minorVersion ),
+            buildNumber( _buildNumber ),
+            branchName( _branchName )
+        {}
+
+        unsigned int const majorVersion;
+        unsigned int const minorVersion;
+        unsigned int const buildNumber;
+        char const* const branchName;
+
+    private:
+        void operator=( Version const& );
+    };
+
+    extern Version libraryVersion;
+}
+
+#include <fstream>
+#include <stdlib.h>
+#include <limits>
+
+namespace Catch {
+
+    class Runner {
+
+    public:
+        Runner( Ptr<Config> const& config )
+        :   m_config( config )
+        {
+            openStream();
+            makeReporter();
+        }
+
+        Totals runTests() {
+
+            std::vector<TestCaseFilters> filterGroups = m_config->filters();
+            if( filterGroups.empty() ) {
+                TestCaseFilters filterGroup( "" );
+                filterGroups.push_back( filterGroup );
+            }
+
+            RunContext context( m_config.get(), m_reporter );
+
+            Totals totals;
+
+            for( std::size_t i=0; i < filterGroups.size() && !context.aborting(); ++i ) {
+                context.testGroupStarting( filterGroups[i].getName(), i, filterGroups.size() );
+                totals += runTestsForGroup( context, filterGroups[i] );
+                context.testGroupEnded( filterGroups[i].getName(), totals, i, filterGroups.size() );
+            }
+            return totals;
+        }
+        Totals runTestsForGroup( RunContext& context, TestCaseFilters const& filterGroup ) {
+            Totals totals;
+
+            std::vector<TestCase> testCases;
+            getRegistryHub().getTestCaseRegistry().getFilteredTests( filterGroup, *m_config, testCases );
+
+            int testsRunForGroup = 0;
+            for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
+                    it != itEnd;
+                    ++it ) {
+                testsRunForGroup++;
+                if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
+
+                    if( context.aborting() )
+                        break;
+
+                    totals += context.runTest( *it );
+                    m_testsAlreadyRun.insert( *it );
+                }
+            }
+            if( testsRunForGroup == 0 && !filterGroup.getName().empty() )
+                m_reporter->noMatchingTestCases( filterGroup.getName() );
+            return totals;
+        }
+
+    private:
+        void openStream() {
+            // Open output file, if specified
+            if( !m_config->getFilename().empty() ) {
+                m_ofs.open( m_config->getFilename().c_str() );
+                if( m_ofs.fail() ) {
+                    std::ostringstream oss;
+                    oss << "Unable to open file: '" << m_config->getFilename() << "'";
+                    throw std::domain_error( oss.str() );
+                }
+                m_config->setStreamBuf( m_ofs.rdbuf() );
+            }
+        }
+        void makeReporter() {
+            std::string reporterName = m_config->getReporterName().empty()
+                ? "console"
+                : m_config->getReporterName();
+
+            m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() );
+            if( !m_reporter ) {
+                std::ostringstream oss;
+                oss << "No reporter registered with name: '" << reporterName << "'";
+                throw std::domain_error( oss.str() );
+            }
+        }
+
+    private:
+        Ptr<Config> m_config;
+        std::ofstream m_ofs;
+        Ptr<IStreamingReporter> m_reporter;
+        std::set<TestCase> m_testsAlreadyRun;
+    };
+
+    class Session {
+        static bool alreadyInstantiated;
+
+    public:
+
+        struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
+
+        Session()
+        : m_cli( makeCommandLineParser() ) {
+            if( alreadyInstantiated ) {
+                std::string msg = "Only one instance of Catch::Session can ever be used";
+                std::cerr << msg << std::endl;
+                throw std::logic_error( msg );
+            }
+            alreadyInstantiated = true;
+        }
+        ~Session() {
+            Catch::cleanUp();
+        }
+
+        void showHelp( std::string const& processName ) {
+            std::cout << "\nCatch v"    << libraryVersion.majorVersion << "."
+                                        << libraryVersion.minorVersion << " build "
+                                        << libraryVersion.buildNumber;
+            if( libraryVersion.branchName != std::string( "master" ) )
+                std::cout << " (" << libraryVersion.branchName << " branch)";
+            std::cout << "\n";
+
+            m_cli.usage( std::cout, processName );
+            std::cout << "For more detail usage please see the project docs\n" << std::endl;
+        }
+
+        int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
+            try {
+                m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
+                m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
+                if( m_configData.showHelp )
+                    showHelp( m_configData.processName );
+                m_config.reset();
+            }
+            catch( std::exception& ex ) {
+                {
+                    Colour colourGuard( Colour::Red );
+                    std::cerr   << "\nError(s) in input:\n"
+                                << Text( ex.what(), TextAttributes().setIndent(2) )
+                                << "\n\n";
+                }
+                m_cli.usage( std::cout, m_configData.processName );
+                return (std::numeric_limits<int>::max)();
+            }
+            return 0;
+        }
+
+        void useConfigData( ConfigData const& _configData ) {
+            m_configData = _configData;
+            m_config.reset();
+        }
+
+        int run( int argc, char* const argv[] ) {
+
+            int returnCode = applyCommandLine( argc, argv );
+            if( returnCode == 0 )
+                returnCode = run();
+            return returnCode;
+        }
+
+        int run() {
+            if( m_configData.showHelp )
+                return 0;
+
+            try
+            {
+                config(); // Force config to be constructed
+                Runner runner( m_config );
+
+                // Handle list request
+                if( Option<std::size_t> listed = list( config() ) )
+                    return static_cast<int>( *listed );
+
+                return static_cast<int>( runner.runTests().assertions.failed );
+            }
+            catch( std::exception& ex ) {
+                std::cerr << ex.what() << std::endl;
+                return (std::numeric_limits<int>::max)();
+            }
+        }
+
+        Clara::CommandLine<ConfigData> const& cli() const {
+            return m_cli;
+        }
+        std::vector<Clara::Parser::Token> const& unusedTokens() const {
+            return m_unusedTokens;
+        }
+        ConfigData& configData() {
+            return m_configData;
+        }
+        Config& config() {
+            if( !m_config )
+                m_config = new Config( m_configData );
+            return *m_config;
+        }
+
+    private:
+        Clara::CommandLine<ConfigData> m_cli;
+        std::vector<Clara::Parser::Token> m_unusedTokens;
+        ConfigData m_configData;
+        Ptr<Config> m_config;
+    };
+
+    bool Session::alreadyInstantiated = false;
+
+} // end namespace Catch
+
+// #included from: catch_registry_hub.hpp
+#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
+
+// #included from: catch_test_case_registry_impl.hpp
+#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
+
+#include <vector>
+#include <set>
+#include <sstream>
+#include <iostream>
+
+namespace Catch {
+
+    class TestRegistry : public ITestCaseRegistry {
+    public:
+        TestRegistry() : m_unnamedCount( 0 ) {}
+        virtual ~TestRegistry();
+
+        virtual void registerTest( TestCase const& testCase ) {
+            std::string name = testCase.getTestCaseInfo().name;
+            if( name == "" ) {
+                std::ostringstream oss;
+                oss << "Anonymous test case " << ++m_unnamedCount;
+                return registerTest( testCase.withName( oss.str() ) );
+            }
+
+            if( m_functions.find( testCase ) == m_functions.end() ) {
+                m_functions.insert( testCase );
+                m_functionsInOrder.push_back( testCase );
+                if( !testCase.isHidden() )
+                    m_nonHiddenFunctions.push_back( testCase );
+            }
+            else {
+                TestCase const& prev = *m_functions.find( testCase );
+                {
+                    Colour colourGuard( Colour::Red );
+                    std::cerr   << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
+                                << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
+                                << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
+                }
+                exit(1);
+            }
+        }
+
+        virtual std::vector<TestCase> const& getAllTests() const {
+            return m_functionsInOrder;
+        }
+
+        virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
+            return m_nonHiddenFunctions;
+        }
+
+        virtual void getFilteredTests( TestCaseFilters const& filters, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
+            for( std::vector<TestCase>::const_iterator  it = m_functionsInOrder.begin(),
+                                                        itEnd = m_functionsInOrder.end();
+                    it != itEnd;
+                    ++it ) {
+                if( filters.shouldInclude( *it ) && ( config.allowThrows() || !it->throws() ) )
+                    matchingTestCases.push_back( *it );
+            }
+        }
+        virtual void getFilteredTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
+            if( config.filters().empty() )
+                return getFilteredTests( TestCaseFilters( "empty" ), config, matchingTestCases );
+
+            for( std::vector<TestCaseFilters>::const_iterator   it = config.filters().begin(),
+                                                                itEnd = config.filters().end();
+                    it != itEnd;
+                    ++it )
+                getFilteredTests( *it, config, matchingTestCases );
+        }
+
+    private:
+
+        std::set<TestCase> m_functions;
+        std::vector<TestCase> m_functionsInOrder;
+        std::vector<TestCase> m_nonHiddenFunctions;
+        size_t m_unnamedCount;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    class FreeFunctionTestCase : public SharedImpl<ITestCase> {
+    public:
+
+        FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
+
+        virtual void invoke() const {
+            m_fun();
+        }
+
+    private:
+        virtual ~FreeFunctionTestCase();
+
+        TestFunction m_fun;
+    };
+
+    inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
+        std::string className = classOrQualifiedMethodName;
+        if( startsWith( className, "&" ) )
+        {
+            std::size_t lastColons = className.rfind( "::" );
+            std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
+            if( penultimateColons == std::string::npos )
+                penultimateColons = 1;
+            className = className.substr( penultimateColons, lastColons-penultimateColons );
+        }
+        return className;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    AutoReg::AutoReg(   TestFunction function,
+                        SourceLineInfo const& lineInfo,
+                        NameAndDesc const& nameAndDesc ) {
+        registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
+    }
+
+    AutoReg::~AutoReg() {}
+
+    void AutoReg::registerTestCase( ITestCase* testCase,
+                                    char const* classOrQualifiedMethodName,
+                                    NameAndDesc const& nameAndDesc,
+                                    SourceLineInfo const& lineInfo ) {
+
+        getMutableRegistryHub().registerTest
+            ( makeTestCase( testCase,
+                            extractClassName( classOrQualifiedMethodName ),
+                            nameAndDesc.name,
+                            nameAndDesc.description,
+                            lineInfo ) );
+    }
+
+} // end namespace Catch
+
+// #included from: catch_reporter_registry.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
+
+#include <map>
+
+namespace Catch {
+
+    class ReporterRegistry : public IReporterRegistry {
+
+    public:
+
+        virtual ~ReporterRegistry() {
+            deleteAllValues( m_factories );
+        }
+
+        virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const {
+            FactoryMap::const_iterator it =  m_factories.find( name );
+            if( it == m_factories.end() )
+                return NULL;
+            return it->second->create( ReporterConfig( config ) );
+        }
+
+        void registerReporter( std::string const& name, IReporterFactory* factory ) {
+            m_factories.insert( std::make_pair( name, factory ) );
+        }
+
+        FactoryMap const& getFactories() const {
+            return m_factories;
+        }
+
+    private:
+        FactoryMap m_factories;
+    };
+}
+
+// #included from: catch_exception_translator_registry.hpp
+#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
+
+#ifdef __OBJC__
+#import "Foundation/Foundation.h"
+#endif
+
+namespace Catch {
+
+    class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
+    public:
+        ~ExceptionTranslatorRegistry() {
+            deleteAll( m_translators );
+        }
+
+        virtual void registerTranslator( const IExceptionTranslator* translator ) {
+            m_translators.push_back( translator );
+        }
+
+        virtual std::string translateActiveException() const {
+            try {
+#ifdef __OBJC__
+                // In Objective-C try objective-c exceptions first
+                @try {
+                    throw;
+                }
+                @catch (NSException *exception) {
+                    return toString( [exception description] );
+                }
+#else
+                throw;
+#endif
+            }
+            catch( std::exception& ex ) {
+                return ex.what();
+            }
+            catch( std::string& msg ) {
+                return msg;
+            }
+            catch( const char* msg ) {
+                return msg;
+            }
+            catch(...) {
+                return tryTranslators( m_translators.begin() );
+            }
+        }
+
+        std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
+            if( it == m_translators.end() )
+                return "Unknown exception";
+
+            try {
+                return (*it)->translate();
+            }
+            catch(...) {
+                return tryTranslators( it+1 );
+            }
+        }
+
+    private:
+        std::vector<const IExceptionTranslator*> m_translators;
+    };
+}
+
+namespace Catch {
+
+    namespace {
+
+        class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
+
+            RegistryHub( RegistryHub const& );
+            void operator=( RegistryHub const& );
+
+        public: // IRegistryHub
+            RegistryHub() {
+            }
+            virtual IReporterRegistry const& getReporterRegistry() const {
+                return m_reporterRegistry;
+            }
+            virtual ITestCaseRegistry const& getTestCaseRegistry() const {
+                return m_testCaseRegistry;
+            }
+            virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
+                return m_exceptionTranslatorRegistry;
+            }
+
+        public: // IMutableRegistryHub
+            virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
+                m_reporterRegistry.registerReporter( name, factory );
+            }
+            virtual void registerTest( TestCase const& testInfo ) {
+                m_testCaseRegistry.registerTest( testInfo );
+            }
+            virtual void registerTranslator( const IExceptionTranslator* translator ) {
+                m_exceptionTranslatorRegistry.registerTranslator( translator );
+            }
+
+        private:
+            TestRegistry m_testCaseRegistry;
+            ReporterRegistry m_reporterRegistry;
+            ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
+        };
+
+        // Single, global, instance
+        inline RegistryHub*& getTheRegistryHub() {
+            static RegistryHub* theRegistryHub = NULL;
+            if( !theRegistryHub )
+                theRegistryHub = new RegistryHub();
+            return theRegistryHub;
+        }
+    }
+
+    IRegistryHub& getRegistryHub() {
+        return *getTheRegistryHub();
+    }
+    IMutableRegistryHub& getMutableRegistryHub() {
+        return *getTheRegistryHub();
+    }
+    void cleanUp() {
+        delete getTheRegistryHub();
+        getTheRegistryHub() = NULL;
+        cleanUpContext();
+    }
+    std::string translateActiveException() {
+        return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
+    }
+
+} // end namespace Catch
+
+// #included from: catch_notimplemented_exception.hpp
+#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
+
+#include <ostream>
+
+namespace Catch {
+
+    NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
+    :   m_lineInfo( lineInfo ) {
+        std::ostringstream oss;
+        oss << lineInfo << ": function ";
+        oss << "not implemented";
+        m_what = oss.str();
+    }
+
+    const char* NotImplementedException::what() const CATCH_NOEXCEPT {
+        return m_what.c_str();
+    }
+
+} // end namespace Catch
+
+// #included from: catch_context_impl.hpp
+#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
+
+// #included from: catch_stream.hpp
+#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
+
+// #included from: catch_streambuf.h
+#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
+
+#include <streambuf>
+
+namespace Catch {
+
+    class StreamBufBase : public std::streambuf {
+    public:
+        virtual ~StreamBufBase() CATCH_NOEXCEPT;
+    };
+}
+
+#include <stdexcept>
+#include <cstdio>
+
+namespace Catch {
+
+    template<typename WriterF, size_t bufferSize=256>
+    class StreamBufImpl : public StreamBufBase {
+        char data[bufferSize];
+        WriterF m_writer;
+
+    public:
+        StreamBufImpl() {
+            setp( data, data + sizeof(data) );
+        }
+
+        ~StreamBufImpl() CATCH_NOEXCEPT {
+            sync();
+        }
+
+    private:
+        int overflow( int c ) {
+            sync();
+
+            if( c != EOF ) {
+                if( pbase() == epptr() )
+                    m_writer( std::string( 1, static_cast<char>( c ) ) );
+                else
+                    sputc( static_cast<char>( c ) );
+            }
+            return 0;
+        }
+
+        int sync() {
+            if( pbase() != pptr() ) {
+                m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
+                setp( pbase(), epptr() );
+            }
+            return 0;
+        }
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    struct OutputDebugWriter {
+
+        void operator()( std::string const&str ) {
+            writeToDebugConsole( str );
+        }
+    };
+
+    Stream::Stream()
+    : streamBuf( NULL ), isOwned( false )
+    {}
+
+    Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
+    : streamBuf( _streamBuf ), isOwned( _isOwned )
+    {}
+
+    void Stream::release() {
+        if( isOwned ) {
+            delete streamBuf;
+            streamBuf = NULL;
+            isOwned = false;
+        }
+    }
+}
+
+namespace Catch {
+
+    class Context : public IMutableContext {
+
+        Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
+        Context( Context const& );
+        void operator=( Context const& );
+
+    public: // IContext
+        virtual IResultCapture& getResultCapture() {
+            return *m_resultCapture;
+        }
+        virtual IRunner& getRunner() {
+            return *m_runner;
+        }
+        virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
+            return getGeneratorsForCurrentTest()
+            .getGeneratorInfo( fileInfo, totalSize )
+            .getCurrentIndex();
+        }
+        virtual bool advanceGeneratorsForCurrentTest() {
+            IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
+            return generators && generators->moveNext();
+        }
+
+        virtual Ptr<IConfig const> getConfig() const {
+            return m_config;
+        }
+
+    public: // IMutableContext
+        virtual void setResultCapture( IResultCapture* resultCapture ) {
+            m_resultCapture = resultCapture;
+        }
+        virtual void setRunner( IRunner* runner ) {
+            m_runner = runner;
+        }
+        virtual void setConfig( Ptr<IConfig const> const& config ) {
+            m_config = config;
+        }
+
+        friend IMutableContext& getCurrentMutableContext();
+
+    private:
+        IGeneratorsForTest* findGeneratorsForCurrentTest() {
+            std::string testName = getResultCapture().getCurrentTestName();
+
+            std::map<std::string, IGeneratorsForTest*>::const_iterator it =
+            m_generatorsByTestName.find( testName );
+            return it != m_generatorsByTestName.end()
+                ? it->second
+                : NULL;
+        }
+
+        IGeneratorsForTest& getGeneratorsForCurrentTest() {
+            IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
+            if( !generators ) {
+                std::string testName = getResultCapture().getCurrentTestName();
+                generators = createGeneratorsForTest();
+                m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
+            }
+            return *generators;
+        }
+
+    private:
+        Ptr<IConfig const> m_config;
+        IRunner* m_runner;
+        IResultCapture* m_resultCapture;
+        std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
+    };
+
+    namespace {
+        Context* currentContext = NULL;
+    }
+    IMutableContext& getCurrentMutableContext() {
+        if( !currentContext )
+            currentContext = new Context();
+        return *currentContext;
+    }
+    IContext& getCurrentContext() {
+        return getCurrentMutableContext();
+    }
+
+    Stream createStream( std::string const& streamName ) {
+        if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
+        if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
+        if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
+
+        throw std::domain_error( "Unknown stream: " + streamName );
+    }
+
+    void cleanUpContext() {
+        delete currentContext;
+        currentContext = NULL;
+    }
+}
+
+// #included from: catch_console_colour_impl.hpp
+#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
+
+namespace Catch { namespace Detail {
+    struct IColourImpl {
+        virtual ~IColourImpl() {}
+        virtual void use( Colour::Code _colourCode ) = 0;
+    };
+}}
+
+#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
+
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
+#ifdef __AFXDLL
+#include <AfxWin.h>
+#else
+#include <windows.h>
+#endif
+
+namespace Catch {
+namespace {
+
+    class Win32ColourImpl : public Detail::IColourImpl {
+    public:
+        Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
+        {
+            CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+            GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
+            originalAttributes = csbiInfo.wAttributes;
+        }
+
+        virtual void use( Colour::Code _colourCode ) {
+            switch( _colourCode ) {
+                case Colour::None:      return setTextAttribute( originalAttributes );
+                case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
+                case Colour::Red:       return setTextAttribute( FOREGROUND_RED );
+                case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );
+                case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );
+                case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
+                case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
+                case Colour::Grey:      return setTextAttribute( 0 );
+
+                case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );
+                case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
+                case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
+                case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
+
+                case Colour::Bright: throw std::logic_error( "not a colour" );
+            }
+        }
+
+    private:
+        void setTextAttribute( WORD _textAttribute ) {
+            SetConsoleTextAttribute( stdoutHandle, _textAttribute );
+        }
+        HANDLE stdoutHandle;
+        WORD originalAttributes;
+    };
+
+    inline bool shouldUseColourForPlatform() {
+        return true;
+    }
+
+    static Detail::IColourImpl* platformColourInstance() {
+        static Win32ColourImpl s_instance;
+        return &s_instance;
+    }
+
+} // end anon namespace
+} // end namespace Catch
+
+#else // Not Windows - assumed to be POSIX compatible //////////////////////////
+
+#include <unistd.h>
+
+namespace Catch {
+namespace {
+
+    // use POSIX/ ANSI console terminal codes
+    // Thanks to Adam Strzelecki for original contribution
+    // (http://github.com/nanoant)
+    // https://github.com/philsquared/Catch/pull/131
+    class PosixColourImpl : public Detail::IColourImpl {
+    public:
+        virtual void use( Colour::Code _colourCode ) {
+            switch( _colourCode ) {
+                case Colour::None:
+                case Colour::White:     return setColour( "[0m" );
+                case Colour::Red:       return setColour( "[0;31m" );
+                case Colour::Green:     return setColour( "[0;32m" );
+                case Colour::Blue:      return setColour( "[0:34m" );
+                case Colour::Cyan:      return setColour( "[0;36m" );
+                case Colour::Yellow:    return setColour( "[0;33m" );
+                case Colour::Grey:      return setColour( "[1;30m" );
+
+                case Colour::LightGrey:     return setColour( "[0;37m" );
+                case Colour::BrightRed:     return setColour( "[1;31m" );
+                case Colour::BrightGreen:   return setColour( "[1;32m" );
+                case Colour::BrightWhite:   return setColour( "[1;37m" );
+
+                case Colour::Bright: throw std::logic_error( "not a colour" );
+            }
+        }
+    private:
+        void setColour( const char* _escapeCode ) {
+            std::cout << '\033' << _escapeCode;
+        }
+    };
+
+    inline bool shouldUseColourForPlatform() {
+        return isatty(STDOUT_FILENO);
+    }
+
+    static Detail::IColourImpl* platformColourInstance() {
+        static PosixColourImpl s_instance;
+        return &s_instance;
+    }
+
+} // end anon namespace
+} // end namespace Catch
+
+#endif // not Windows
+
+namespace Catch {
+
+    namespace {
+        struct NoColourImpl : Detail::IColourImpl {
+            void use( Colour::Code ) {}
+
+            static IColourImpl* instance() {
+                static NoColourImpl s_instance;
+                return &s_instance;
+            }
+        };
+        static bool shouldUseColour() {
+            return shouldUseColourForPlatform() && !isDebuggerActive();
+        }
+    }
+
+    Colour::Colour( Code _colourCode ){ use( _colourCode ); }
+    Colour::~Colour(){ use( None ); }
+    void Colour::use( Code _colourCode ) {
+        impl()->use( _colourCode );
+    }
+
+    Detail::IColourImpl* Colour::impl() {
+        return shouldUseColour()
+            ? platformColourInstance()
+            : NoColourImpl::instance();
+    }
+
+} // end namespace Catch
+
+// #included from: catch_generators_impl.hpp
+#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
+
+#include <vector>
+#include <string>
+#include <map>
+
+namespace Catch {
+
+    struct GeneratorInfo : IGeneratorInfo {
+
+        GeneratorInfo( std::size_t size )
+        :   m_size( size ),
+            m_currentIndex( 0 )
+        {}
+
+        bool moveNext() {
+            if( ++m_currentIndex == m_size ) {
+                m_currentIndex = 0;
+                return false;
+            }
+            return true;
+        }
+
+        std::size_t getCurrentIndex() const {
+            return m_currentIndex;
+        }
+
+        std::size_t m_size;
+        std::size_t m_currentIndex;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    class GeneratorsForTest : public IGeneratorsForTest {
+
+    public:
+        ~GeneratorsForTest() {
+            deleteAll( m_generatorsInOrder );
+        }
+
+        IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
+            std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
+            if( it == m_generatorsByName.end() ) {
+                IGeneratorInfo* info = new GeneratorInfo( size );
+                m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
+                m_generatorsInOrder.push_back( info );
+                return *info;
+            }
+            return *it->second;
+        }
+
+        bool moveNext() {
+            std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
+            std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
+            for(; it != itEnd; ++it ) {
+                if( (*it)->moveNext() )
+                    return true;
+            }
+            return false;
+        }
+
+    private:
+        std::map<std::string, IGeneratorInfo*> m_generatorsByName;
+        std::vector<IGeneratorInfo*> m_generatorsInOrder;
+    };
+
+    IGeneratorsForTest* createGeneratorsForTest()
+    {
+        return new GeneratorsForTest();
+    }
+
+} // end namespace Catch
+
+// #included from: catch_assertionresult.hpp
+#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
+
+namespace Catch {
+
+    AssertionInfo::AssertionInfo(   std::string const& _macroName,
+                                    SourceLineInfo const& _lineInfo,
+                                    std::string const& _capturedExpression,
+                                    ResultDisposition::Flags _resultDisposition )
+    :   macroName( _macroName ),
+        lineInfo( _lineInfo ),
+        capturedExpression( _capturedExpression ),
+        resultDisposition( _resultDisposition )
+    {}
+
+    AssertionResult::AssertionResult() {}
+
+    AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
+    :   m_info( info ),
+        m_resultData( data )
+    {}
+
+    AssertionResult::~AssertionResult() {}
+
+    // Result was a success
+    bool AssertionResult::succeeded() const {
+        return Catch::isOk( m_resultData.resultType );
+    }
+
+    // Result was a success, or failure is suppressed
+    bool AssertionResult::isOk() const {
+        return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
+    }
+
+    ResultWas::OfType AssertionResult::getResultType() const {
+        return m_resultData.resultType;
+    }
+
+    bool AssertionResult::hasExpression() const {
+        return !m_info.capturedExpression.empty();
+    }
+
+    bool AssertionResult::hasMessage() const {
+        return !m_resultData.message.empty();
+    }
+
+    std::string AssertionResult::getExpression() const {
+        if( shouldNegate( m_info.resultDisposition ) )
+            return "!" + m_info.capturedExpression;
+        else
+            return m_info.capturedExpression;
+    }
+    std::string AssertionResult::getExpressionInMacro() const {
+        if( m_info.macroName.empty() )
+            return m_info.capturedExpression;
+        else
+            return m_info.macroName + "( " + m_info.capturedExpression + " )";
+    }
+
+    bool AssertionResult::hasExpandedExpression() const {
+        return hasExpression() && getExpandedExpression() != getExpression();
+    }
+
+    std::string AssertionResult::getExpandedExpression() const {
+        return m_resultData.reconstructedExpression;
+    }
+
+    std::string AssertionResult::getMessage() const {
+        return m_resultData.message;
+    }
+    SourceLineInfo AssertionResult::getSourceInfo() const {
+        return m_info.lineInfo;
+    }
+
+    std::string AssertionResult::getTestMacroName() const {
+        return m_info.macroName;
+    }
+
+} // end namespace Catch
+
+// #included from: catch_expressionresult_builder.hpp
+#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
+
+#include <assert.h>
+
+namespace Catch {
+
+    ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) {
+        m_data.resultType = resultType;
+    }
+    ExpressionResultBuilder::ExpressionResultBuilder( ExpressionResultBuilder const& other )
+    :   m_data( other.m_data ),
+        m_exprComponents( other.m_exprComponents )
+    {
+        m_stream << other.m_stream.str();
+    }
+    ExpressionResultBuilder& ExpressionResultBuilder::operator=(ExpressionResultBuilder const& other ) {
+        m_data = other.m_data;
+        m_exprComponents = other.m_exprComponents;
+        m_stream.str("");
+        m_stream << other.m_stream.str();
+        return *this;
+    }
+    ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) {
+        m_data.resultType = result;
+        return *this;
+    }
+    ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) {
+        m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
+        return *this;
+    }
+    ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) {
+        m_exprComponents.shouldNegate = shouldNegate( resultDisposition );
+        return *this;
+    }
+    ExpressionResultBuilder& ExpressionResultBuilder::setLhs( std::string const& lhs ) {
+        m_exprComponents.lhs = lhs;
+        return *this;
+    }
+    ExpressionResultBuilder& ExpressionResultBuilder::setRhs( std::string const& rhs ) {
+        m_exprComponents.rhs = rhs;
+        return *this;
+    }
+    ExpressionResultBuilder& ExpressionResultBuilder::setOp( std::string const& op ) {
+        m_exprComponents.op = op;
+        return *this;
+    }
+    AssertionResult ExpressionResultBuilder::buildResult( AssertionInfo const& info ) const
+    {
+        assert( m_data.resultType != ResultWas::Unknown );
+
+        AssertionResultData data = m_data;
+
+        // Flip bool results if shouldNegate is set
+        if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok )
+            data.resultType = ResultWas::ExpressionFailed;
+        else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed )
+            data.resultType = ResultWas::Ok;
+
+        data.message = m_stream.str();
+        data.reconstructedExpression = reconstructExpression( info );
+        if( m_exprComponents.shouldNegate ) {
+            if( m_exprComponents.op == "" )
+                data.reconstructedExpression = "!" + data.reconstructedExpression;
+            else
+                data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
+        }
+        return AssertionResult( info, data );
+    }
+    std::string ExpressionResultBuilder::reconstructExpression( AssertionInfo const& info ) const {
+        if( m_exprComponents.op == "" )
+            return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
+        else if( m_exprComponents.op == "matches" )
+            return m_exprComponents.lhs + " " + m_exprComponents.rhs;
+        else if( m_exprComponents.op != "!" ) {
+            if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
+                m_exprComponents.lhs.find("\n") == std::string::npos &&
+                m_exprComponents.rhs.find("\n") == std::string::npos )
+                return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
+            else
+                return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
+        }
+        else
+            return "{can't expand - use " + info.macroName + "_FALSE( " + info.capturedExpression.substr(1) + " ) instead of " + info.macroName + "( " + info.capturedExpression + " ) for better diagnostics}";
+    }
+
+} // end namespace Catch
+
+// #included from: catch_test_case_info.hpp
+#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
+
+namespace Catch {
+
+    inline bool isSpecialTag( std::string const& tag ) {
+        return  tag == "." ||
+                tag == "hide" ||
+                tag == "!hide" ||
+                tag == "!throws";
+    }
+    inline bool isReservedTag( std::string const& tag ) {
+        return !isSpecialTag( tag ) && tag.size() > 0 && !isalnum( tag[0] );
+    }
+
+    TestCase makeTestCase(  ITestCase* _testCase,
+                            std::string const& _className,
+                            std::string const& _name,
+                            std::string const& _descOrTags,
+                            SourceLineInfo const& _lineInfo )
+    {
+        std::string desc = _descOrTags;
+        bool isHidden( startsWith( _name, "./" ) ); // Legacy support
+        std::set<std::string> tags;
+        TagExtracter( tags ).parse( desc );
+        for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end();
+                it != itEnd;
+                ++it )
+            if( isReservedTag( *it ) ) {
+                {
+                    Colour colourGuard( Colour::Red );
+                    std::cerr
+                        << "Tag name [" << *it << "] not allowed.\n"
+                        << "Tag names starting with non alpha-numeric characters are reserved\n";
+                }
+                {
+                    Colour colourGuard( Colour::FileName );
+                    std::cerr << _lineInfo << std::endl;
+                }
+                exit(1);
+            }
+
+        if( tags.find( "hide" ) != tags.end() || tags.find( "." ) != tags.end() )
+            isHidden = true;
+
+        if( isHidden ) {
+            tags.insert( "hide" );
+            tags.insert( "." );
+        }
+        TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo );
+        return TestCase( _testCase, info );
+    }
+
+    TestCaseInfo::TestCaseInfo( std::string const& _name,
+                                std::string const& _className,
+                                std::string const& _description,
+                                std::set<std::string> const& _tags,
+                                bool _isHidden,
+                                SourceLineInfo const& _lineInfo )
+    :   name( _name ),
+        className( _className ),
+        description( _description ),
+        tags( _tags ),
+        lineInfo( _lineInfo ),
+        isHidden( _isHidden ),
+        throws( false )
+    {
+        std::ostringstream oss;
+        for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {
+            oss << "[" << *it << "]";
+            if( *it == "!throws" )
+                throws = true;
+        }
+        tagsAsString = oss.str();
+    }
+
+    TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
+    :   name( other.name ),
+        className( other.className ),
+        description( other.description ),
+        tags( other.tags ),
+        tagsAsString( other.tagsAsString ),
+        lineInfo( other.lineInfo ),
+        isHidden( other.isHidden ),
+        throws( other.throws )
+    {}
+
+    TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
+
+    TestCase::TestCase( TestCase const& other )
+    :   TestCaseInfo( other ),
+        test( other.test )
+    {}
+
+    TestCase TestCase::withName( std::string const& _newName ) const {
+        TestCase other( *this );
+        other.name = _newName;
+        return other;
+    }
+
+    void TestCase::invoke() const {
+        test->invoke();
+    }
+
+    bool TestCase::isHidden() const {
+        return TestCaseInfo::isHidden;
+    }
+    bool TestCase::throws() const {
+        return TestCaseInfo::throws;
+    }
+
+    bool TestCase::hasTag( std::string const& tag ) const {
+        return tags.find( toLower( tag ) ) != tags.end();
+    }
+    bool TestCase::matchesTags( std::string const& tagPattern ) const {
+        TagExpression exp;
+        TagExpressionParser( exp ).parse( tagPattern );
+        return exp.matches( tags );
+    }
+    std::set<std::string> const& TestCase::getTags() const {
+        return tags;
+    }
+
+    void TestCase::swap( TestCase& other ) {
+        test.swap( other.test );
+        className.swap( other.className );
+        name.swap( other.name );
+        description.swap( other.description );
+        std::swap( lineInfo, other.lineInfo );
+    }
+
+    bool TestCase::operator == ( TestCase const& other ) const {
+        return  test.get() == other.test.get() &&
+                name == other.name &&
+                className == other.className;
+    }
+
+    bool TestCase::operator < ( TestCase const& other ) const {
+        return name < other.name;
+    }
+    TestCase& TestCase::operator = ( TestCase const& other ) {
+        TestCase temp( other );
+        swap( temp );
+        return *this;
+    }
+
+    TestCaseInfo const& TestCase::getTestCaseInfo() const
+    {
+        return *this;
+    }
+
+} // end namespace Catch
+
+// #included from: catch_tags.hpp
+#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
+
+namespace Catch {
+    TagParser::~TagParser() {}
+
+    void TagParser::parse( std::string const& str ) {
+        std::size_t pos = 0;
+        while( pos < str.size() ) {
+            char c = str[pos];
+            if( c == '[' ) {
+                std::size_t end = str.find_first_of( ']', pos );
+                if( end != std::string::npos ) {
+                    acceptTag( str.substr( pos+1, end-pos-1 ) );
+                    pos = end+1;
+                }
+                else {
+                    acceptChar( c );
+                    pos++;
+                }
+            }
+            else {
+                acceptChar( c );
+                pos++;
+            }
+        }
+        endParse();
+    }
+
+    TagExtracter::TagExtracter( std::set<std::string>& tags )
+    :   m_tags( tags )
+    {}
+
+    TagExtracter::~TagExtracter() {}
+
+    void TagExtracter::parse( std::string& description ) {
+        TagParser::parse( description );
+        description = m_remainder;
+    }
+
+    void TagExtracter::acceptTag( std::string const& tag ) {
+        m_tags.insert( toLower( tag ) );
+    }
+    void TagExtracter::acceptChar( char c ) {
+        m_remainder += c;
+    }
+
+    Tag::Tag() : m_isNegated( false ) {}
+    Tag::Tag( std::string const& name, bool isNegated )
+    :   m_name( name ),
+        m_isNegated( isNegated )
+    {}
+
+    std::string Tag::getName() const {
+        return m_name;
+    }
+    bool Tag::isNegated() const {
+        return m_isNegated;
+    }
+
+    bool Tag::operator ! () const {
+        return m_name.empty();
+    }
+
+    void TagSet::add( Tag const& tag ) {
+        m_tags.insert( std::make_pair( toLower( tag.getName() ), tag ) );
+    }
+
+    bool TagSet::empty() const {
+        return m_tags.empty();
+    }
+
+    bool TagSet::matches( std::set<std::string> const& tags ) const {
+        for(    TagMap::const_iterator
+                    it = m_tags.begin(), itEnd = m_tags.end();
+                it != itEnd;
+                ++it ) {
+            bool found = tags.find( it->first ) != tags.end();
+            if( found == it->second.isNegated() )
+                return false;
+        }
+        return true;
+    }
+
+    bool TagExpression::matches( std::set<std::string> const& tags ) const {
+        for(    std::vector<TagSet>::const_iterator
+                    it = m_tagSets.begin(), itEnd = m_tagSets.end();
+                it != itEnd;
+                ++it )
+            if( it->matches( tags ) )
+                return true;
+        return false;
+    }
+
+    TagExpressionParser::TagExpressionParser( TagExpression& exp )
+    :   m_isNegated( false ),
+        m_exp( exp )
+    {}
+
+    TagExpressionParser::~TagExpressionParser() {}
+
+    void TagExpressionParser::acceptTag( std::string const& tag ) {
+        m_currentTagSet.add( Tag( tag, m_isNegated ) );
+        m_isNegated = false;
+    }
+
+    void TagExpressionParser::acceptChar( char c ) {
+        switch( c ) {
+            case '~':
+                m_isNegated = true;
+                break;
+            case ',':
+                m_exp.m_tagSets.push_back( m_currentTagSet );
+                m_currentTagSet = TagSet();
+                break;
+        }
+    }
+
+    void TagExpressionParser::endParse() {
+        if( !m_currentTagSet.empty() )
+            m_exp.m_tagSets.push_back( m_currentTagSet );
+    }
+
+} // end namespace Catch
+
+// #included from: catch_test_spec.hpp
+#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
+
+namespace Catch {
+
+    TestCaseFilter::TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour )
+    :   m_stringToMatch( toLower( testSpec ) ),
+        m_filterType( matchBehaviour ),
+        m_wildcardPosition( NoWildcard )
+    {
+        if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
+            if( startsWith( m_stringToMatch, "exclude:" ) ) {
+                m_stringToMatch = m_stringToMatch.substr( 8 );
+                m_filterType = IfFilterMatches::ExcludeTests;
+            }
+            else if( startsWith( m_stringToMatch, "~" ) ) {
+                m_stringToMatch = m_stringToMatch.substr( 1 );
+                m_filterType = IfFilterMatches::ExcludeTests;
+            }
+            else {
+                m_filterType = IfFilterMatches::IncludeTests;
+            }
+        }
+
+        if( startsWith( m_stringToMatch, "*" ) ) {
+            m_stringToMatch = m_stringToMatch.substr( 1 );
+            m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
+        }
+        if( endsWith( m_stringToMatch, "*" ) ) {
+            m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
+            m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
+        }
+    }
+
+    IfFilterMatches::DoWhat TestCaseFilter::getFilterType() const {
+        return m_filterType;
+    }
+
+    bool TestCaseFilter::shouldInclude( TestCase const& testCase ) const {
+        return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
+    }
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunreachable-code"
+#endif
+
+    bool TestCaseFilter::isMatch( TestCase const& testCase ) const {
+        std::string name = testCase.getTestCaseInfo().name;
+        toLowerInPlace( name );
+
+        switch( m_wildcardPosition ) {
+            case NoWildcard:
+                return m_stringToMatch == name;
+            case WildcardAtStart:
+                return endsWith( name, m_stringToMatch );
+            case WildcardAtEnd:
+                return startsWith( name, m_stringToMatch );
+            case WildcardAtBothEnds:
+                return contains( name, m_stringToMatch );
+        }
+        throw std::logic_error( "Unhandled wildcard type" );
+    }
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+    TestCaseFilters::TestCaseFilters( std::string const& name ) : m_name( name ) {}
+
+    std::string TestCaseFilters::getName() const {
+        return m_name;
+    }
+
+    void TestCaseFilters::addFilter( TestCaseFilter const& filter ) {
+        if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
+            m_exclusionFilters.push_back( filter );
+        else
+            m_inclusionFilters.push_back( filter );
+    }
+
+    void TestCaseFilters::addTags( std::string const& tagPattern ) {
+        TagExpression exp;
+        TagExpressionParser( exp ).parse( tagPattern );
+
+        m_tagExpressions.push_back( exp );
+    }
+
+    bool TestCaseFilters::shouldInclude( TestCase const& testCase ) const {
+        if( !m_tagExpressions.empty() ) {
+            std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
+            std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
+            for(; it != itEnd; ++it )
+                if( it->matches( testCase.getTags() ) )
+                    break;
+            if( it == itEnd )
+                return false;
+        }
+
+        if( !m_inclusionFilters.empty() ) {
+            std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
+            std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
+            for(; it != itEnd; ++it )
+                if( it->shouldInclude( testCase ) )
+                    break;
+            if( it == itEnd )
+                return false;
+        }
+        else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
+            return !testCase.isHidden();
+        }
+
+        std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
+        std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
+        for(; it != itEnd; ++it )
+            if( !it->shouldInclude( testCase ) )
+                return false;
+        return true;
+    }
+}
+
+// #included from: catch_version.hpp
+#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
+
+namespace Catch {
+
+    // These numbers are maintained by a script
+    Version libraryVersion( 1, 0, 43, "master" );
+}
+
+// #included from: catch_message.hpp
+#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
+
+namespace Catch {
+
+    MessageInfo::MessageInfo(   std::string const& _macroName,
+                                SourceLineInfo const& _lineInfo,
+                                ResultWas::OfType _type )
+    :   macroName( _macroName ),
+        lineInfo( _lineInfo ),
+        type( _type ),
+        sequence( ++globalCount )
+    {}
+
+    // This may need protecting if threading support is added
+    unsigned int MessageInfo::globalCount = 0;
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    ScopedMessage::ScopedMessage( MessageBuilder const& builder )
+    : m_info( builder.m_info )
+    {
+        m_info.message = builder.m_stream.str();
+        getResultCapture().pushScopedMessage( m_info );
+    }
+    ScopedMessage::~ScopedMessage() {
+        getResultCapture().popScopedMessage( m_info );
+    }
+
+} // end namespace Catch
+
+// #included from: catch_legacy_reporter_adapter.hpp
+#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
+
+// #included from: catch_legacy_reporter_adapter.h
+#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
+
+namespace Catch
+{
+    // Deprecated
+    struct IReporter : IShared {
+        virtual ~IReporter();
+
+        virtual bool shouldRedirectStdout() const = 0;
+
+        virtual void StartTesting() = 0;
+        virtual void EndTesting( Totals const& totals ) = 0;
+        virtual void StartGroup( std::string const& groupName ) = 0;
+        virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
+        virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
+        virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
+        virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
+        virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
+        virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
+        virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
+        virtual void Aborted() = 0;
+        virtual void Result( AssertionResult const& result ) = 0;
+    };
+
+    class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
+    {
+    public:
+        LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
+        virtual ~LegacyReporterAdapter();
+
+        virtual ReporterPreferences getPreferences() const;
+        virtual void noMatchingTestCases( std::string const& );
+        virtual void testRunStarting( TestRunInfo const& );
+        virtual void testGroupStarting( GroupInfo const& groupInfo );
+        virtual void testCaseStarting( TestCaseInfo const& testInfo );
+        virtual void sectionStarting( SectionInfo const& sectionInfo );
+        virtual void assertionStarting( AssertionInfo const& );
+        virtual bool assertionEnded( AssertionStats const& assertionStats );
+        virtual void sectionEnded( SectionStats const& sectionStats );
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats );
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats );
+        virtual void testRunEnded( TestRunStats const& testRunStats );
+
+    private:
+        Ptr<IReporter> m_legacyReporter;
+    };
+}
+
+namespace Catch
+{
+    LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
+    :   m_legacyReporter( legacyReporter )
+    {}
+    LegacyReporterAdapter::~LegacyReporterAdapter() {}
+
+    ReporterPreferences LegacyReporterAdapter::getPreferences() const {
+        ReporterPreferences prefs;
+        prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
+        return prefs;
+    }
+
+    void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
+    void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
+        m_legacyReporter->StartTesting();
+    }
+    void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
+        m_legacyReporter->StartGroup( groupInfo.name );
+    }
+    void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
+        m_legacyReporter->StartTestCase( testInfo );
+    }
+    void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
+        m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
+    }
+    void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
+        // Not on legacy interface
+    }
+
+    bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
+        if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
+            for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
+                    it != itEnd;
+                    ++it ) {
+                if( it->type == ResultWas::Info ) {
+                    ExpressionResultBuilder expressionBuilder( it->type );
+                        expressionBuilder << it->message;
+                    AssertionInfo info( it->macroName, it->lineInfo, "", ResultDisposition::Normal );
+                    AssertionResult result = expressionBuilder.buildResult( info );
+                    m_legacyReporter->Result( result );
+                }
+            }
+        }
+        m_legacyReporter->Result( assertionStats.assertionResult );
+        return true;
+    }
+    void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
+        if( sectionStats.missingAssertions )
+            m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
+        m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
+    }
+    void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
+        m_legacyReporter->EndTestCase
+            (   testCaseStats.testInfo,
+                testCaseStats.totals,
+                testCaseStats.stdOut,
+                testCaseStats.stdErr );
+    }
+    void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
+        if( testGroupStats.aborting )
+            m_legacyReporter->Aborted();
+        m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
+    }
+    void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
+        m_legacyReporter->EndTesting( testRunStats.totals );
+    }
+}
+
+// #included from: catch_timer.hpp
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++11-long-long"
+#endif
+
+#ifdef CATCH_PLATFORM_WINDOWS
+#include <windows.h>
+#else
+#include <sys/time.h>
+#endif
+
+namespace Catch {
+
+    namespace {
+#ifdef CATCH_PLATFORM_WINDOWS
+        uint64_t getCurrentTicks() {
+            static uint64_t hz=0, hzo=0;
+            if (!hz) {
+                QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
+                QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
+            }
+            uint64_t t;
+            QueryPerformanceCounter((LARGE_INTEGER*)&t);
+            return ((t-hzo)*1000000)/hz;
+        }
+#else
+        uint64_t getCurrentTicks() {
+            timeval t;
+            gettimeofday(&t,NULL);
+            return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec;
+        }
+#endif
+    }
+
+    void Timer::start() {
+        m_ticks = getCurrentTicks();
+    }
+    unsigned int Timer::getElapsedNanoseconds() const {
+        return (unsigned int)(getCurrentTicks() - m_ticks);
+    }
+    unsigned int Timer::getElapsedMilliseconds() const {
+        return (unsigned int)((getCurrentTicks() - m_ticks)/1000);
+    }
+    double Timer::getElapsedSeconds() const {
+        return (getCurrentTicks() - m_ticks)/1000000.0;
+    }
+
+} // namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+// #included from: catch_common.hpp
+#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
+
+namespace Catch {
+
+    bool startsWith( std::string const& s, std::string const& prefix ) {
+        return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
+    }
+    bool endsWith( std::string const& s, std::string const& suffix ) {
+        return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
+    }
+    bool contains( std::string const& s, std::string const& infix ) {
+        return s.find( infix ) != std::string::npos;
+    }
+    void toLowerInPlace( std::string& s ) {
+        std::transform( s.begin(), s.end(), s.begin(), ::tolower );
+    }
+    std::string toLower( std::string const& s ) {
+        std::string lc = s;
+        toLowerInPlace( lc );
+        return lc;
+    }
+    std::string trim( std::string const& str ) {
+        static char const* whitespaceChars = "\n\r\t ";
+        std::string::size_type start = str.find_first_not_of( whitespaceChars );
+        std::string::size_type end = str.find_last_not_of( whitespaceChars );
+
+        return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
+    }
+
+    pluralise::pluralise( std::size_t count, std::string const& label )
+    :   m_count( count ),
+        m_label( label )
+    {}
+
+    std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
+        os << pluraliser.m_count << " " << pluraliser.m_label;
+        if( pluraliser.m_count != 1 )
+            os << "s";
+        return os;
+    }
+
+    SourceLineInfo::SourceLineInfo() : line( 0 ){}
+    SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
+    :   file( _file ),
+        line( _line )
+    {}
+    SourceLineInfo::SourceLineInfo( SourceLineInfo const& other )
+    :   file( other.file ),
+        line( other.line )
+    {}
+    bool SourceLineInfo::empty() const {
+        return file.empty();
+    }
+    bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
+        return line == other.line && file == other.file;
+    }
+
+    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
+#ifndef __GNUG__
+        os << info.file << "(" << info.line << ")";
+#else
+        os << info.file << ":" << info.line;
+#endif
+        return os;
+    }
+
+    void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
+        std::ostringstream oss;
+        oss << locationInfo << ": Internal Catch error: '" << message << "'";
+        if( isTrue( true ))
+            throw std::logic_error( oss.str() );
+    }
+}
+
+// #included from: catch_section.hpp
+#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
+
+namespace Catch {
+
+    Section::Section(   SourceLineInfo const& lineInfo,
+                        std::string const& name,
+                        std::string const& description )
+    :   m_info( name, description, lineInfo ),
+        m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) )
+    {
+        m_timer.start();
+    }
+
+    Section::~Section() {
+        if( m_sectionIncluded )
+            getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
+    }
+
+    // This indicates whether the section should be executed or not
+    Section::operator bool() {
+        return m_sectionIncluded;
+    }
+
+} // end namespace Catch
+
+// #included from: catch_debugger.hpp
+#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
+
+#include <iostream>
+
+#ifdef CATCH_PLATFORM_MAC
+
+    #include <assert.h>
+    #include <stdbool.h>
+    #include <sys/types.h>
+    #include <unistd.h>
+    #include <sys/sysctl.h>
+
+    namespace Catch{
+
+        // The following function is taken directly from the following technical note:
+        // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
+
+        // Returns true if the current process is being debugged (either
+        // running under the debugger or has a debugger attached post facto).
+        bool isDebuggerActive(){
+
+            int                 mib[4];
+            struct kinfo_proc   info;
+            size_t              size;
+
+            // Initialize the flags so that, if sysctl fails for some bizarre
+            // reason, we get a predictable result.
+
+            info.kp_proc.p_flag = 0;
+
+            // Initialize mib, which tells sysctl the info we want, in this case
+            // we're looking for information about a specific process ID.
+
+            mib[0] = CTL_KERN;
+            mib[1] = KERN_PROC;
+            mib[2] = KERN_PROC_PID;
+            mib[3] = getpid();
+
+            // Call sysctl.
+
+            size = sizeof(info);
+            if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
+                std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
+                return false;
+            }
+
+            // We're being debugged if the P_TRACED flag is set.
+
+            return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
+        }
+    } // namespace Catch
+
+#elif defined(_MSC_VER)
+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+    namespace Catch {
+        bool isDebuggerActive() {
+            return IsDebuggerPresent() != 0;
+        }
+    }
+#elif defined(__MINGW32__)
+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+    namespace Catch {
+        bool isDebuggerActive() {
+            return IsDebuggerPresent() != 0;
+        }
+    }
+#else
+    namespace Catch {
+       inline bool isDebuggerActive() { return false; }
+    }
+#endif // Platform
+
+#ifdef CATCH_PLATFORM_WINDOWS
+    extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
+    namespace Catch {
+        void writeToDebugConsole( std::string const& text ) {
+            ::OutputDebugStringA( text.c_str() );
+        }
+    }
+#else
+    namespace Catch {
+        void writeToDebugConsole( std::string const& text ) {
+            // !TBD: Need a version for Mac/ XCode and other IDEs
+            std::cout << text;
+        }
+    }
+#endif // Platform
+
+// #included from: catch_tostring.hpp
+#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
+
+namespace Catch {
+
+std::string toString( std::string const& value ) {
+    std::string s = value;
+    if( getCurrentContext().getConfig()->showInvisibles() ) {
+        for(size_t i = 0; i < s.size(); ++i ) {
+            std::string subs;
+            switch( s[i] ) {
+            case '\n': subs = "\\n"; break;
+            case '\t': subs = "\\t"; break;
+            default: break;
+            }
+            if( !subs.empty() ) {
+                s = s.substr( 0, i ) + subs + s.substr( i+1 );
+                ++i;
+            }
+        }
+    }
+    return "\"" + s + "\"";
+}
+std::string toString( std::wstring const& value ) {
+
+    std::string s;
+    s.reserve( value.size() );
+    for(size_t i = 0; i < value.size(); ++i )
+        s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
+    return toString( s );
+}
+
+std::string toString( const char* const value ) {
+    return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
+}
+
+std::string toString( char* const value ) {
+    return Catch::toString( static_cast<const char*>( value ) );
+}
+
+std::string toString( int value ) {
+    std::ostringstream oss;
+    oss << value;
+    return oss.str();
+}
+
+std::string toString( unsigned long value ) {
+    std::ostringstream oss;
+    if( value > 8192 )
+        oss << "0x" << std::hex << value;
+    else
+        oss << value;
+    return oss.str();
+}
+
+std::string toString( unsigned int value ) {
+    return toString( static_cast<unsigned long>( value ) );
+}
+
+std::string toString( const double value ) {
+    std::ostringstream oss;
+    oss << std::setprecision( 10 )
+        << std::fixed
+        << value;
+    std::string d = oss.str();
+    std::size_t i = d.find_last_not_of( '0' );
+    if( i != std::string::npos && i != d.size()-1 ) {
+        if( d[i] == '.' )
+            i++;
+        d = d.substr( 0, i+1 );
+    }
+    return d;
+}
+
+std::string toString( bool value ) {
+    return value ? "true" : "false";
+}
+
+std::string toString( char value ) {
+    return value < ' '
+        ? toString( static_cast<unsigned int>( value ) )
+        : Detail::makeString( value );
+}
+
+std::string toString( signed char value ) {
+    return toString( static_cast<char>( value ) );
+}
+
+std::string toString( unsigned char value ) {
+    return toString( static_cast<char>( value ) );
+}
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+std::string toString( std::nullptr_t ) {
+    return "nullptr";
+}
+#endif
+
+#ifdef __OBJC__
+    std::string toString( NSString const * const& nsstring ) {
+        if( !nsstring )
+            return "nil";
+        return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
+    }
+    std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
+        if( !nsstring )
+            return "nil";
+        return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
+    }
+    std::string toString( NSObject* const& nsObject ) {
+        return toString( [nsObject description] );
+    }
+#endif
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_xml.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
+
+// #included from: catch_reporter_bases.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
+
+namespace Catch {
+
+    struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
+
+        StreamingReporterBase( ReporterConfig const& _config )
+        :   m_config( _config.fullConfig() ),
+            stream( _config.stream() )
+        {}
+
+        virtual ~StreamingReporterBase();
+
+        virtual void noMatchingTestCases( std::string const& ) {}
+
+        virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
+            currentTestRunInfo = _testRunInfo;
+        }
+        virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
+            currentGroupInfo = _groupInfo;
+        }
+
+        virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
+            currentTestCaseInfo = _testInfo;
+        }
+        virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
+            m_sectionStack.push_back( _sectionInfo );
+        }
+
+        virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
+            m_sectionStack.pop_back();
+        }
+        virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
+            currentTestCaseInfo.reset();
+            assert( m_sectionStack.empty() );
+        }
+        virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
+            currentGroupInfo.reset();
+        }
+        virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
+            currentTestCaseInfo.reset();
+            currentGroupInfo.reset();
+            currentTestRunInfo.reset();
+        }
+
+        Ptr<IConfig> m_config;
+        std::ostream& stream;
+
+        LazyStat<TestRunInfo> currentTestRunInfo;
+        LazyStat<GroupInfo> currentGroupInfo;
+        LazyStat<TestCaseInfo> currentTestCaseInfo;
+
+        std::vector<SectionInfo> m_sectionStack;
+    };
+
+    struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
+        template<typename T, typename ChildNodeT>
+        struct Node : SharedImpl<> {
+            explicit Node( T const& _value ) : value( _value ) {}
+            virtual ~Node() {}
+
+            typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
+            T value;
+            ChildNodes children;
+        };
+        struct SectionNode : SharedImpl<> {
+            explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
+            virtual ~SectionNode();
+
+            bool operator == ( SectionNode const& other ) const {
+                return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
+            }
+            bool operator == ( Ptr<SectionNode> const& other ) const {
+                return operator==( *other );
+            }
+
+            SectionStats stats;
+            typedef std::vector<Ptr<SectionNode> > ChildSections;
+            typedef std::vector<AssertionStats> Assertions;
+            ChildSections childSections;
+            Assertions assertions;
+            std::string stdOut;
+            std::string stdErr;
+        };
+
+        struct BySectionInfo {
+            BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
+            bool operator() ( Ptr<SectionNode> const& node ) const {
+                return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
+            }
+        private:
+            BySectionInfo& operator=( BySectionInfo const& other ); // = delete;
+
+            SectionInfo const& m_other;
+        };
+
+        typedef Node<TestCaseStats, SectionNode> TestCaseNode;
+        typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
+        typedef Node<TestRunStats, TestGroupNode> TestRunNode;
+
+        CumulativeReporterBase( ReporterConfig const& _config )
+        :   m_config( _config.fullConfig() ),
+            stream( _config.stream() )
+        {}
+        ~CumulativeReporterBase();
+
+        virtual void testRunStarting( TestRunInfo const& ) {}
+        virtual void testGroupStarting( GroupInfo const& ) {}
+
+        virtual void testCaseStarting( TestCaseInfo const& ) {}
+
+        virtual void sectionStarting( SectionInfo const& sectionInfo ) {
+            SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
+            Ptr<SectionNode> node;
+            if( m_sectionStack.empty() ) {
+                if( !m_rootSection )
+                    m_rootSection = new SectionNode( incompleteStats );
+                node = m_rootSection;
+            }
+            else {
+                SectionNode& parentNode = *m_sectionStack.back();
+                SectionNode::ChildSections::const_iterator it =
+                    std::find_if(   parentNode.childSections.begin(),
+                                    parentNode.childSections.end(),
+                                    BySectionInfo( sectionInfo ) );
+                if( it == parentNode.childSections.end() ) {
+                    node = new SectionNode( incompleteStats );
+                    parentNode.childSections.push_back( node );
+                }
+                else
+                    node = *it;
+            }
+            m_sectionStack.push_back( node );
+            m_deepestSection = node;
+        }
+
+        virtual void assertionStarting( AssertionInfo const& ) {}
+
+        virtual bool assertionEnded( AssertionStats const& assertionStats ) {
+            assert( !m_sectionStack.empty() );
+            SectionNode& sectionNode = *m_sectionStack.back();
+            sectionNode.assertions.push_back( assertionStats );
+            return true;
+        }
+        virtual void sectionEnded( SectionStats const& sectionStats ) {
+            assert( !m_sectionStack.empty() );
+            SectionNode& node = *m_sectionStack.back();
+            node.stats = sectionStats;
+            m_sectionStack.pop_back();
+        }
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
+            Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
+            assert( m_sectionStack.size() == 0 );
+            node->children.push_back( m_rootSection );
+            m_testCases.push_back( node );
+            m_rootSection.reset();
+
+            assert( m_deepestSection );
+            m_deepestSection->stdOut = testCaseStats.stdOut;
+            m_deepestSection->stdErr = testCaseStats.stdErr;
+        }
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
+            Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
+            node->children.swap( m_testCases );
+            m_testGroups.push_back( node );
+        }
+        virtual void testRunEnded( TestRunStats const& testRunStats ) {
+            Ptr<TestRunNode> node = new TestRunNode( testRunStats );
+            node->children.swap( m_testGroups );
+            m_testRuns.push_back( node );
+            testRunEndedCumulative();
+        }
+        virtual void testRunEndedCumulative() = 0;
+
+        Ptr<IConfig> m_config;
+        std::ostream& stream;
+        std::vector<AssertionStats> m_assertions;
+        std::vector<std::vector<Ptr<SectionNode> > > m_sections;
+        std::vector<Ptr<TestCaseNode> > m_testCases;
+        std::vector<Ptr<TestGroupNode> > m_testGroups;
+
+        std::vector<Ptr<TestRunNode> > m_testRuns;
+
+        Ptr<SectionNode> m_rootSection;
+        Ptr<SectionNode> m_deepestSection;
+        std::vector<Ptr<SectionNode> > m_sectionStack;
+
+    };
+
+} // end namespace Catch
+
+// #included from: ../internal/catch_reporter_registrars.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
+
+namespace Catch {
+
+    template<typename T>
+    class LegacyReporterRegistrar {
+
+        class ReporterFactory : public IReporterFactory {
+            virtual IStreamingReporter* create( ReporterConfig const& config ) const {
+                return new LegacyReporterAdapter( new T( config ) );
+            }
+
+            virtual std::string getDescription() const {
+                return T::getDescription();
+            }
+        };
+
+    public:
+
+        LegacyReporterRegistrar( std::string const& name ) {
+            getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
+        }
+    };
+
+    template<typename T>
+    class ReporterRegistrar {
+
+        class ReporterFactory : public IReporterFactory {
+
+            // *** Please Note ***:
+            // - If you end up here looking at a compiler error because it's trying to register
+            // your custom reporter class be aware that the native reporter interface has changed
+            // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
+            // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
+            // However please consider updating to the new interface as the old one is now
+            // deprecated and will probably be removed quite soon!
+            // Please contact me via github if you have any questions at all about this.
+            // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
+            // no idea who is actually using custom reporters at all (possibly no-one!).
+            // The new interface is designed to minimise exposure to interface changes in the future.
+            virtual IStreamingReporter* create( ReporterConfig const& config ) const {
+                return new T( config );
+            }
+
+            virtual std::string getDescription() const {
+                return T::getDescription();
+            }
+        };
+
+    public:
+
+        ReporterRegistrar( std::string const& name ) {
+            getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
+        }
+    };
+}
+
+#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
+    namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
+    namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+
+// #included from: ../internal/catch_xmlwriter.hpp
+#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
+
+#include <sstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace Catch {
+
+    class XmlWriter {
+    public:
+
+        class ScopedElement {
+        public:
+            ScopedElement( XmlWriter* writer )
+            :   m_writer( writer )
+            {}
+
+            ScopedElement( ScopedElement const& other )
+            :   m_writer( other.m_writer ){
+                other.m_writer = NULL;
+            }
+
+            ~ScopedElement() {
+                if( m_writer )
+                    m_writer->endElement();
+            }
+
+            ScopedElement& writeText( std::string const& text, bool indent = true ) {
+                m_writer->writeText( text, indent );
+                return *this;
+            }
+
+            template<typename T>
+            ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
+                m_writer->writeAttribute( name, attribute );
+                return *this;
+            }
+
+        private:
+            mutable XmlWriter* m_writer;
+        };
+
+        XmlWriter()
+        :   m_tagIsOpen( false ),
+            m_needsNewline( false ),
+            m_os( &std::cout )
+        {}
+
+        XmlWriter( std::ostream& os )
+        :   m_tagIsOpen( false ),
+            m_needsNewline( false ),
+            m_os( &os )
+        {}
+
+        ~XmlWriter() {
+            while( !m_tags.empty() )
+                endElement();
+        }
+
+#  ifndef CATCH_CPP11_OR_GREATER
+        XmlWriter& operator = ( XmlWriter const& other ) {
+            XmlWriter temp( other );
+            swap( temp );
+            return *this;
+        }
+#  else
+        XmlWriter( XmlWriter const& )              = default;
+        XmlWriter( XmlWriter && )                  = default;
+        XmlWriter& operator = ( XmlWriter const& ) = default;
+        XmlWriter& operator = ( XmlWriter && )     = default;
+#  endif
+
+        void swap( XmlWriter& other ) {
+            std::swap( m_tagIsOpen, other.m_tagIsOpen );
+            std::swap( m_needsNewline, other.m_needsNewline );
+            std::swap( m_tags, other.m_tags );
+            std::swap( m_indent, other.m_indent );
+            std::swap( m_os, other.m_os );
+        }
+
+        XmlWriter& startElement( std::string const& name ) {
+            ensureTagClosed();
+            newlineIfNecessary();
+            stream() << m_indent << "<" << name;
+            m_tags.push_back( name );
+            m_indent += "  ";
+            m_tagIsOpen = true;
+            return *this;
+        }
+
+        ScopedElement scopedElement( std::string const& name ) {
+            ScopedElement scoped( this );
+            startElement( name );
+            return scoped;
+        }
+
+        XmlWriter& endElement() {
+            newlineIfNecessary();
+            m_indent = m_indent.substr( 0, m_indent.size()-2 );
+            if( m_tagIsOpen ) {
+                stream() << "/>\n";
+                m_tagIsOpen = false;
+            }
+            else {
+                stream() << m_indent << "</" << m_tags.back() << ">\n";
+            }
+            m_tags.pop_back();
+            return *this;
+        }
+
+        XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
+            if( !name.empty() && !attribute.empty() ) {
+                stream() << " " << name << "=\"";
+                writeEncodedText( attribute );
+                stream() << "\"";
+            }
+            return *this;
+        }
+
+        XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
+            stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
+            return *this;
+        }
+
+        template<typename T>
+        XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
+            if( !name.empty() )
+                stream() << " " << name << "=\"" << attribute << "\"";
+            return *this;
+        }
+
+        XmlWriter& writeText( std::string const& text, bool indent = true ) {
+            if( !text.empty() ){
+                bool tagWasOpen = m_tagIsOpen;
+                ensureTagClosed();
+                if( tagWasOpen && indent )
+                    stream() << m_indent;
+                writeEncodedText( text );
+                m_needsNewline = true;
+            }
+            return *this;
+        }
+
+        XmlWriter& writeComment( std::string const& text ) {
+            ensureTagClosed();
+            stream() << m_indent << "<!--" << text << "-->";
+            m_needsNewline = true;
+            return *this;
+        }
+
+        XmlWriter& writeBlankLine() {
+            ensureTagClosed();
+            stream() << "\n";
+            return *this;
+        }
+
+    private:
+
+        std::ostream& stream() {
+            return *m_os;
+        }
+
+        void ensureTagClosed() {
+            if( m_tagIsOpen ) {
+                stream() << ">\n";
+                m_tagIsOpen = false;
+            }
+        }
+
+        void newlineIfNecessary() {
+            if( m_needsNewline ) {
+                stream() << "\n";
+                m_needsNewline = false;
+            }
+        }
+
+        void writeEncodedText( std::string const& text ) {
+            static const char* charsToEncode = "<&\"";
+            std::string mtext = text;
+            std::string::size_type pos = mtext.find_first_of( charsToEncode );
+            while( pos != std::string::npos ) {
+                stream() << mtext.substr( 0, pos );
+
+                switch( mtext[pos] ) {
+                    case '<':
+                        stream() << "&lt;";
+                        break;
+                    case '&':
+                        stream() << "&amp;";
+                        break;
+                    case '\"':
+                        stream() << "&quot;";
+                        break;
+                }
+                mtext = mtext.substr( pos+1 );
+                pos = mtext.find_first_of( charsToEncode );
+            }
+            stream() << mtext;
+        }
+
+        bool m_tagIsOpen;
+        bool m_needsNewline;
+        std::vector<std::string> m_tags;
+        std::string m_indent;
+        std::ostream* m_os;
+    };
+
+}
+namespace Catch {
+    class XmlReporter : public SharedImpl<IReporter> {
+    public:
+        XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {}
+
+        static std::string getDescription() {
+            return "Reports test results as an XML document";
+        }
+        virtual ~XmlReporter();
+
+    private: // IReporter
+
+        virtual bool shouldRedirectStdout() const {
+            return true;
+        }
+
+        virtual void StartTesting() {
+            m_xml = XmlWriter( m_config.stream() );
+            m_xml.startElement( "Catch" );
+            if( !m_config.fullConfig()->name().empty() )
+                m_xml.writeAttribute( "name", m_config.fullConfig()->name() );
+        }
+
+        virtual void EndTesting( const Totals& totals ) {
+            m_xml.scopedElement( "OverallResults" )
+                .writeAttribute( "successes", totals.assertions.passed )
+                .writeAttribute( "failures", totals.assertions.failed );
+            m_xml.endElement();
+        }
+
+        virtual void StartGroup( const std::string& groupName ) {
+            m_xml.startElement( "Group" )
+                .writeAttribute( "name", groupName );
+        }
+
+        virtual void EndGroup( const std::string&, const Totals& totals ) {
+            m_xml.scopedElement( "OverallResults" )
+                .writeAttribute( "successes", totals.assertions.passed )
+                .writeAttribute( "failures", totals.assertions.failed );
+            m_xml.endElement();
+        }
+
+        virtual void StartSection( const std::string& sectionName, const std::string& description ) {
+            if( m_sectionDepth++ > 0 ) {
+                m_xml.startElement( "Section" )
+                    .writeAttribute( "name", trim( sectionName ) )
+                    .writeAttribute( "description", description );
+            }
+        }
+        virtual void NoAssertionsInSection( const std::string& ) {}
+        virtual void NoAssertionsInTestCase( const std::string& ) {}
+
+        virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
+            if( --m_sectionDepth > 0 ) {
+                m_xml.scopedElement( "OverallResults" )
+                    .writeAttribute( "successes", assertions.passed )
+                    .writeAttribute( "failures", assertions.failed );
+                m_xml.endElement();
+            }
+        }
+
+        virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
+            m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
+            m_currentTestSuccess = true;
+        }
+
+        virtual void Result( const Catch::AssertionResult& assertionResult ) {
+            if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok )
+                return;
+
+            if( assertionResult.hasExpression() ) {
+                m_xml.startElement( "Expression" )
+                    .writeAttribute( "success", assertionResult.succeeded() )
+                    .writeAttribute( "filename", assertionResult.getSourceInfo().file )
+                    .writeAttribute( "line", assertionResult.getSourceInfo().line );
+
+                m_xml.scopedElement( "Original" )
+                    .writeText( assertionResult.getExpression() );
+                m_xml.scopedElement( "Expanded" )
+                    .writeText( assertionResult.getExpandedExpression() );
+                m_currentTestSuccess &= assertionResult.succeeded();
+            }
+
+            switch( assertionResult.getResultType() ) {
+                case ResultWas::ThrewException:
+                    m_xml.scopedElement( "Exception" )
+                        .writeAttribute( "filename", assertionResult.getSourceInfo().file )
+                        .writeAttribute( "line", assertionResult.getSourceInfo().line )
+                        .writeText( assertionResult.getMessage() );
+                    m_currentTestSuccess = false;
+                    break;
+                case ResultWas::Info:
+                    m_xml.scopedElement( "Info" )
+                        .writeText( assertionResult.getMessage() );
+                    break;
+                case ResultWas::Warning:
+                    m_xml.scopedElement( "Warning" )
+                        .writeText( assertionResult.getMessage() );
+                    break;
+                case ResultWas::ExplicitFailure:
+                    m_xml.scopedElement( "Failure" )
+                        .writeText( assertionResult.getMessage() );
+                    m_currentTestSuccess = false;
+                    break;
+                case ResultWas::Unknown:
+                case ResultWas::Ok:
+                case ResultWas::FailureBit:
+                case ResultWas::ExpressionFailed:
+                case ResultWas::Exception:
+                case ResultWas::DidntThrowException:
+                    break;
+            }
+            if( assertionResult.hasExpression() )
+                m_xml.endElement();
+        }
+
+        virtual void Aborted() {
+            // !TBD
+        }
+
+        virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
+            m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
+            m_xml.endElement();
+        }
+
+    private:
+        ReporterConfig m_config;
+        bool m_currentTestSuccess;
+        XmlWriter m_xml;
+        int m_sectionDepth;
+    };
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_junit.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
+
+#include <assert.h>
+
+namespace Catch {
+
+    class JunitReporter : public CumulativeReporterBase {
+    public:
+        JunitReporter( ReporterConfig const& _config )
+        :   CumulativeReporterBase( _config ),
+            xml( _config.stream() )
+        {}
+
+        ~JunitReporter();
+
+        static std::string getDescription() {
+            return "Reports test results in an XML format that looks like Ant's junitreport target";
+        }
+
+        virtual void noMatchingTestCases( std::string const& /*spec*/ ) {}
+
+        virtual ReporterPreferences getPreferences() const {
+            ReporterPreferences prefs;
+            prefs.shouldRedirectStdOut = true;
+            return prefs;
+        }
+
+        virtual void testRunStarting( TestRunInfo const& runInfo ) {
+            CumulativeReporterBase::testRunStarting( runInfo );
+            xml.startElement( "testsuites" );
+        }
+
+        virtual void testGroupStarting( GroupInfo const& groupInfo ) {
+            suiteTimer.start();
+            stdOutForSuite.str("");
+            stdErrForSuite.str("");
+            unexpectedExceptions = 0;
+            CumulativeReporterBase::testGroupStarting( groupInfo );
+        }
+
+        virtual bool assertionEnded( AssertionStats const& assertionStats ) {
+            if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
+                unexpectedExceptions++;
+            return CumulativeReporterBase::assertionEnded( assertionStats );
+        }
+
+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
+            stdOutForSuite << testCaseStats.stdOut;
+            stdErrForSuite << testCaseStats.stdErr;
+            CumulativeReporterBase::testCaseEnded( testCaseStats );
+        }
+
+        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
+            double suiteTime = suiteTimer.getElapsedSeconds();
+            CumulativeReporterBase::testGroupEnded( testGroupStats );
+            writeGroup( *m_testGroups.back(), suiteTime );
+        }
+
+        virtual void testRunEndedCumulative() {
+            xml.endElement();
+        }
+
+        void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
+            XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
+            TestGroupStats const& stats = groupNode.value;
+            xml.writeAttribute( "name", stats.groupInfo.name );
+            xml.writeAttribute( "errors", unexpectedExceptions );
+            xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
+            xml.writeAttribute( "tests", stats.totals.assertions.total() );
+            xml.writeAttribute( "hostname", "tbd" ); // !TBD
+            if( m_config->showDurations() == ShowDurations::Never )
+                xml.writeAttribute( "time", "" );
+            else
+                xml.writeAttribute( "time", suiteTime );
+            xml.writeAttribute( "timestamp", "tbd" ); // !TBD
+
+            // Write test cases
+            for( TestGroupNode::ChildNodes::const_iterator
+                    it = groupNode.children.begin(), itEnd = groupNode.children.end();
+                    it != itEnd;
+                    ++it )
+                writeTestCase( **it );
+
+            xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
+            xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
+        }
+
+        void writeTestCase( TestCaseNode const& testCaseNode ) {
+            TestCaseStats const& stats = testCaseNode.value;
+
+            // All test cases have exactly one section - which represents the
+            // test case itself. That section may have 0-n nested sections
+            assert( testCaseNode.children.size() == 1 );
+            SectionNode const& rootSection = *testCaseNode.children.front();
+
+            std::string className = stats.testInfo.className;
+
+            if( className.empty() ) {
+                if( rootSection.childSections.empty() )
+                    className = "global";
+            }
+            writeSection( className, "", rootSection );
+        }
+
+        void writeSection(  std::string const& className,
+                            std::string const& rootName,
+                            SectionNode const& sectionNode ) {
+            std::string name = trim( sectionNode.stats.sectionInfo.name );
+            if( !rootName.empty() )
+                name = rootName + "/" + name;
+
+            if( !sectionNode.assertions.empty() ||
+                !sectionNode.stdOut.empty() ||
+                !sectionNode.stdErr.empty() ) {
+                XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
+                if( className.empty() ) {
+                    xml.writeAttribute( "classname", name );
+                    xml.writeAttribute( "name", "root" );
+                }
+                else {
+                    xml.writeAttribute( "classname", className );
+                    xml.writeAttribute( "name", name );
+                }
+                xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) );
+
+                writeAssertions( sectionNode );
+
+                if( !sectionNode.stdOut.empty() )
+                    xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
+                if( !sectionNode.stdErr.empty() )
+                    xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
+            }
+            for( SectionNode::ChildSections::const_iterator
+                    it = sectionNode.childSections.begin(),
+                    itEnd = sectionNode.childSections.end();
+                    it != itEnd;
+                    ++it )
+                if( className.empty() )
+                    writeSection( name, "", **it );
+                else
+                    writeSection( className, name, **it );
+        }
+
+        void writeAssertions( SectionNode const& sectionNode ) {
+            for( SectionNode::Assertions::const_iterator
+                    it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
+                    it != itEnd;
+                    ++it )
+                writeAssertion( *it );
+        }
+        void writeAssertion( AssertionStats const& stats ) {
+            AssertionResult const& result = stats.assertionResult;
+            if( !result.isOk() ) {
+                std::string elementName;
+                switch( result.getResultType() ) {
+                    case ResultWas::ThrewException:
+                        elementName = "error";
+                        break;
+                    case ResultWas::ExplicitFailure:
+                        elementName = "failure";
+                        break;
+                    case ResultWas::ExpressionFailed:
+                        elementName = "failure";
+                        break;
+                    case ResultWas::DidntThrowException:
+                        elementName = "failure";
+                        break;
+
+                    // We should never see these here:
+                    case ResultWas::Info:
+                    case ResultWas::Warning:
+                    case ResultWas::Ok:
+                    case ResultWas::Unknown:
+                    case ResultWas::FailureBit:
+                    case ResultWas::Exception:
+                        elementName = "internalError";
+                        break;
+                }
+
+                XmlWriter::ScopedElement e = xml.scopedElement( elementName );
+
+                xml.writeAttribute( "message", result.getExpandedExpression() );
+                xml.writeAttribute( "type", result.getTestMacroName() );
+
+                std::ostringstream oss;
+                if( !result.getMessage().empty() )
+                    oss << result.getMessage() << "\n";
+                for( std::vector<MessageInfo>::const_iterator
+                        it = stats.infoMessages.begin(),
+                        itEnd = stats.infoMessages.end();
+                            it != itEnd;
+                            ++it )
+                    if( it->type == ResultWas::Info )
+                        oss << it->message << "\n";
+
+                oss << "at " << result.getSourceInfo();
+                xml.writeText( oss.str(), false );
+            }
+        }
+
+        XmlWriter xml;
+        Timer suiteTimer;
+        std::ostringstream stdOutForSuite;
+        std::ostringstream stdErrForSuite;
+        unsigned int unexpectedExceptions;
+    };
+
+    INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_console.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
+
+#include <cstring>
+
+namespace Catch {
+
+    struct ConsoleReporter : StreamingReporterBase {
+        ConsoleReporter( ReporterConfig const& _config )
+        :   StreamingReporterBase( _config ),
+            m_headerPrinted( false ),
+            m_atLeastOneTestCasePrinted( false )
+        {}
+
+        virtual ~ConsoleReporter();
+        static std::string getDescription() {
+            return "Reports test results as plain lines of text";
+        }
+        virtual ReporterPreferences getPreferences() const {
+            ReporterPreferences prefs;
+            prefs.shouldRedirectStdOut = false;
+            return prefs;
+        }
+
+        virtual void noMatchingTestCases( std::string const& spec ) {
+            stream << "No test cases matched '" << spec << "'" << std::endl;
+        }
+
+        virtual void assertionStarting( AssertionInfo const& ) {
+        }
+
+        virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
+            AssertionResult const& result = _assertionStats.assertionResult;
+
+            bool printInfoMessages = true;
+
+            // Drop out if result was successful and we're not printing those
+            if( !m_config->includeSuccessfulResults() && result.isOk() ) {
+                if( result.getResultType() != ResultWas::Warning )
+                    return false;
+                printInfoMessages = false;
+            }
+
+            lazyPrint();
+
+            AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
+            printer.print();
+            stream << std::endl;
+            return true;
+        }
+
+        virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
+            m_headerPrinted = false;
+            StreamingReporterBase::sectionStarting( _sectionInfo );
+        }
+        virtual void sectionEnded( SectionStats const& _sectionStats ) {
+            if( _sectionStats.missingAssertions ) {
+                lazyPrint();
+                Colour colour( Colour::ResultError );
+                if( m_sectionStack.size() > 1 )
+                    stream << "\nNo assertions in section";
+                else
+                    stream << "\nNo assertions in test case";
+                stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
+            }
+            if( m_headerPrinted ) {
+                if( m_config->showDurations() == ShowDurations::Always )
+                    stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
+                m_headerPrinted = false;
+            }
+            else {
+                if( m_config->showDurations() == ShowDurations::Always )
+                    stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
+            }
+            StreamingReporterBase::sectionEnded( _sectionStats );
+        }
+
+        virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) {
+            StreamingReporterBase::testCaseEnded( _testCaseStats );
+            m_headerPrinted = false;
+        }
+        virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) {
+            if( currentGroupInfo.used ) {
+                printSummaryDivider();
+                stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
+                printTotals( _testGroupStats.totals );
+                stream << "\n" << std::endl;
+            }
+            StreamingReporterBase::testGroupEnded( _testGroupStats );
+        }
+        virtual void testRunEnded( TestRunStats const& _testRunStats ) {
+            if( m_atLeastOneTestCasePrinted )
+                printTotalsDivider();
+            printTotals( _testRunStats.totals );
+            stream << "\n" << std::endl;
+            StreamingReporterBase::testRunEnded( _testRunStats );
+        }
+
+    private:
+
+        class AssertionPrinter {
+            void operator= ( AssertionPrinter const& );
+        public:
+            AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
+            :   stream( _stream ),
+                stats( _stats ),
+                result( _stats.assertionResult ),
+                colour( Colour::None ),
+                message( result.getMessage() ),
+                messages( _stats.infoMessages ),
+                printInfoMessages( _printInfoMessages )
+            {
+                switch( result.getResultType() ) {
+                    case ResultWas::Ok:
+                        colour = Colour::Success;
+                        passOrFail = "PASSED";
+                        //if( result.hasMessage() )
+                        if( _stats.infoMessages.size() == 1 )
+                            messageLabel = "with message";
+                        if( _stats.infoMessages.size() > 1 )
+                            messageLabel = "with messages";
+                        break;
+                    case ResultWas::ExpressionFailed:
+                        if( result.isOk() ) {
+                            colour = Colour::Success;
+                            passOrFail = "FAILED - but was ok";
+                        }
+                        else {
+                            colour = Colour::Error;
+                            passOrFail = "FAILED";
+                        }
+                        if( _stats.infoMessages.size() == 1 )
+                            messageLabel = "with message";
+                        if( _stats.infoMessages.size() > 1 )
+                            messageLabel = "with messages";
+                        break;
+                    case ResultWas::ThrewException:
+                        colour = Colour::Error;
+                        passOrFail = "FAILED";
+                        messageLabel = "due to unexpected exception with message";
+                        break;
+                    case ResultWas::DidntThrowException:
+                        colour = Colour::Error;
+                        passOrFail = "FAILED";
+                        messageLabel = "because no exception was thrown where one was expected";
+                        break;
+                    case ResultWas::Info:
+                        messageLabel = "info";
+                        break;
+                    case ResultWas::Warning:
+                        messageLabel = "warning";
+                        break;
+                    case ResultWas::ExplicitFailure:
+                        passOrFail = "FAILED";
+                        colour = Colour::Error;
+                        if( _stats.infoMessages.size() == 1 )
+                            messageLabel = "explicitly with message";
+                        if( _stats.infoMessages.size() > 1 )
+                            messageLabel = "explicitly with messages";
+                        break;
+                    // These cases are here to prevent compiler warnings
+                    case ResultWas::Unknown:
+                    case ResultWas::FailureBit:
+                    case ResultWas::Exception:
+                        passOrFail = "** internal error **";
+                        colour = Colour::Error;
+                        break;
+                }
+            }
+
+            void print() const {
+                printSourceInfo();
+                if( stats.totals.assertions.total() > 0 ) {
+                    if( result.isOk() )
+                        stream << "\n";
+                    printResultType();
+                    printOriginalExpression();
+                    printReconstructedExpression();
+                }
+                else {
+                    stream << "\n";
+                }
+                printMessage();
+            }
+
+        private:
+            void printResultType() const {
+                if( !passOrFail.empty() ) {
+                    Colour colourGuard( colour );
+                    stream << passOrFail << ":\n";
+                }
+            }
+            void printOriginalExpression() const {
+                if( result.hasExpression() ) {
+                    Colour colourGuard( Colour::OriginalExpression );
+                    stream  << "  ";
+                    stream << result.getExpressionInMacro();
+                    stream << "\n";
+                }
+            }
+            void printReconstructedExpression() const {
+                if( result.hasExpandedExpression() ) {
+                    stream << "with expansion:\n";
+                    Colour colourGuard( Colour::ReconstructedExpression );
+                    stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n";
+                }
+            }
+            void printMessage() const {
+                if( !messageLabel.empty() )
+                    stream << messageLabel << ":" << "\n";
+                for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
+                        it != itEnd;
+                        ++it ) {
+                    // If this assertion is a warning ignore any INFO messages
+                    if( printInfoMessages || it->type != ResultWas::Info )
+                        stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
+                }
+            }
+            void printSourceInfo() const {
+                Colour colourGuard( Colour::FileName );
+                stream << result.getSourceInfo() << ": ";
+            }
+
+            std::ostream& stream;
+            AssertionStats const& stats;
+            AssertionResult const& result;
+            Colour::Code colour;
+            std::string passOrFail;
+            std::string messageLabel;
+            std::string message;
+            std::vector<MessageInfo> messages;
+            bool printInfoMessages;
+        };
+
+        void lazyPrint() {
+
+            if( !currentTestRunInfo.used )
+                lazyPrintRunInfo();
+            if( !currentGroupInfo.used )
+                lazyPrintGroupInfo();
+
+            if( !m_headerPrinted ) {
+                printTestCaseAndSectionHeader();
+                m_headerPrinted = true;
+            }
+            m_atLeastOneTestCasePrinted = true;
+        }
+        void lazyPrintRunInfo() {
+            stream  << "\n" << getLineOfChars<'~'>() << "\n";
+            Colour colour( Colour::SecondaryText );
+            stream  << currentTestRunInfo->name
+                    << " is a Catch v"  << libraryVersion.majorVersion << "."
+                    << libraryVersion.minorVersion << " b"
+                    << libraryVersion.buildNumber;
+            if( libraryVersion.branchName != std::string( "master" ) )
+                stream << " (" << libraryVersion.branchName << ")";
+            stream  << " host application.\n"
+                    << "Run with -? for options\n\n";
+
+            currentTestRunInfo.used = true;
+        }
+        void lazyPrintGroupInfo() {
+            if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
+                printClosedHeader( "Group: " + currentGroupInfo->name );
+                currentGroupInfo.used = true;
+            }
+        }
+        void printTestCaseAndSectionHeader() {
+            assert( !m_sectionStack.empty() );
+            printOpenHeader( currentTestCaseInfo->name );
+
+            if( m_sectionStack.size() > 1 ) {
+                Colour colourGuard( Colour::Headers );
+
+                std::vector<SectionInfo>::const_iterator
+                    it = m_sectionStack.begin()+1, // Skip first section (test case)
+                    itEnd = m_sectionStack.end();
+                for( ; it != itEnd; ++it )
+                    printHeaderString( it->name, 2 );
+            }
+
+            SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
+
+            if( !lineInfo.empty() ){
+                stream << getLineOfChars<'-'>() << "\n";
+                Colour colourGuard( Colour::FileName );
+                stream << lineInfo << "\n";
+            }
+            stream << getLineOfChars<'.'>() << "\n" << std::endl;
+        }
+
+        void printClosedHeader( std::string const& _name ) {
+            printOpenHeader( _name );
+            stream << getLineOfChars<'.'>() << "\n";
+        }
+        void printOpenHeader( std::string const& _name ) {
+            stream  << getLineOfChars<'-'>() << "\n";
+            {
+                Colour colourGuard( Colour::Headers );
+                printHeaderString( _name );
+            }
+        }
+
+        // if string has a : in first line will set indent to follow it on
+        // subsequent lines
+        void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
+            std::size_t i = _string.find( ": " );
+            if( i != std::string::npos )
+                i+=2;
+            else
+                i = 0;
+            stream << Text( _string, TextAttributes()
+                                        .setIndent( indent+i)
+                                        .setInitialIndent( indent ) ) << "\n";
+        }
+
+        void printTotals( const Totals& totals ) {
+            if( totals.testCases.total() == 0 ) {
+                stream << "No tests ran";
+            }
+            else if( totals.assertions.total() == 0 ) {
+                Colour colour( Colour::Yellow );
+                printCounts( "test case", totals.testCases );
+                stream << " (no assertions)";
+            }
+            else if( totals.assertions.failed ) {
+                Colour colour( Colour::ResultError );
+                printCounts( "test case", totals.testCases );
+                if( totals.testCases.failed > 0 ) {
+                    stream << " (";
+                    printCounts( "assertion", totals.assertions );
+                    stream << ")";
+                }
+            }
+            else {
+                Colour colour( Colour::ResultSuccess );
+                stream << "All tests passed ("
+                        << pluralise( totals.assertions.passed, "assertion" ) << " in "
+                        << pluralise( totals.testCases.passed, "test case" ) << ")";
+            }
+        }
+        void printCounts( std::string const& label, Counts const& counts ) {
+            if( counts.total() == 1 ) {
+                stream << "1 " << label << " - ";
+                if( counts.failed )
+                    stream << "failed";
+                else
+                    stream << "passed";
+            }
+            else {
+                stream << counts.total() << " " << label << "s ";
+                if( counts.passed ) {
+                    if( counts.failed )
+                        stream << "- " << counts.failed << " failed";
+                    else if( counts.passed == 2 )
+                        stream << "- both passed";
+                    else
+                        stream << "- all passed";
+                }
+                else {
+                    if( counts.failed == 2 )
+                        stream << "- both failed";
+                    else
+                        stream << "- all failed";
+                }
+            }
+        }
+
+        void printTotalsDivider() {
+            stream << getLineOfChars<'='>() << "\n";
+        }
+        void printSummaryDivider() {
+            stream << getLineOfChars<'-'>() << "\n";
+        }
+        template<char C>
+        static char const* getLineOfChars() {
+            static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
+            if( !*line ) {
+                memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
+                line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
+            }
+            return line;
+        }
+
+    private:
+        bool m_headerPrinted;
+        bool m_atLeastOneTestCasePrinted;
+    };
+
+    INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_compact.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
+
+namespace Catch {
+
+    struct CompactReporter : StreamingReporterBase {
+
+        CompactReporter( ReporterConfig const& _config )
+        : StreamingReporterBase( _config )
+        {}
+
+        virtual ~CompactReporter();
+
+        static std::string getDescription() {
+            return "Reports test results on a single line, suitable for IDEs";
+        }
+
+        virtual ReporterPreferences getPreferences() const {
+            ReporterPreferences prefs;
+            prefs.shouldRedirectStdOut = false;
+            return prefs;
+        }
+
+        virtual void noMatchingTestCases( std::string const& spec ) {
+            stream << "No test cases matched '" << spec << "'" << std::endl;
+        }
+
+        virtual void assertionStarting( AssertionInfo const& ) {
+        }
+
+        virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
+            AssertionResult const& result = _assertionStats.assertionResult;
+
+            bool printInfoMessages = true;
+
+            // Drop out if result was successful and we're not printing those
+            if( !m_config->includeSuccessfulResults() && result.isOk() ) {
+                if( result.getResultType() != ResultWas::Warning )
+                    return false;
+                printInfoMessages = false;
+            }
+
+            AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
+            printer.print();
+
+            stream << std::endl;
+            return true;
+        }
+
+        virtual void testRunEnded( TestRunStats const& _testRunStats ) {
+            printTotals( _testRunStats.totals );
+            stream << "\n" << std::endl;
+            StreamingReporterBase::testRunEnded( _testRunStats );
+        }
+
+    private:
+        class AssertionPrinter {
+            void operator= ( AssertionPrinter const& );
+        public:
+            AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
+            : stream( _stream )
+            , stats( _stats )
+            , result( _stats.assertionResult )
+            , messages( _stats.infoMessages )
+            , itMessage( _stats.infoMessages.begin() )
+            , printInfoMessages( _printInfoMessages )
+            {}
+
+            void print() {
+                printSourceInfo();
+
+                itMessage = messages.begin();
+
+                switch( result.getResultType() ) {
+                    case ResultWas::Ok:
+                        printResultType( Colour::ResultSuccess, passedString() );
+                        printOriginalExpression();
+                        printReconstructedExpression();
+                        if ( ! result.hasExpression() )
+                            printRemainingMessages( Colour::None );
+                        else
+                            printRemainingMessages();
+                        break;
+                    case ResultWas::ExpressionFailed:
+                        if( result.isOk() )
+                            printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
+                        else
+                            printResultType( Colour::Error, failedString() );
+                        printOriginalExpression();
+                        printReconstructedExpression();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::ThrewException:
+                        printResultType( Colour::Error, failedString() );
+                        printIssue( "unexpected exception with message:" );
+                        printMessage();
+                        printExpressionWas();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::DidntThrowException:
+                        printResultType( Colour::Error, failedString() );
+                        printIssue( "expected exception, got none" );
+                        printExpressionWas();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::Info:
+                        printResultType( Colour::None, "info" );
+                        printMessage();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::Warning:
+                        printResultType( Colour::None, "warning" );
+                        printMessage();
+                        printRemainingMessages();
+                        break;
+                    case ResultWas::ExplicitFailure:
+                        printResultType( Colour::Error, failedString() );
+                        printIssue( "explicitly" );
+                        printRemainingMessages( Colour::None );
+                        break;
+                    // These cases are here to prevent compiler warnings
+                    case ResultWas::Unknown:
+                    case ResultWas::FailureBit:
+                    case ResultWas::Exception:
+                        printResultType( Colour::Error, "** internal error **" );
+                        break;
+                }
+            }
+
+        private:
+            // Colour::LightGrey
+
+            static Colour dimColour() { return Colour::FileName; }
+
+#ifdef CATCH_PLATFORM_MAC
+            static const char* failedString() { return "FAILED"; }
+            static const char* passedString() { return "PASSED"; }
+#else
+            static const char* failedString() { return "failed"; }
+            static const char* passedString() { return "passed"; }
+#endif
+
+            void printSourceInfo() const {
+                Colour colourGuard( Colour::FileName );
+                stream << result.getSourceInfo() << ":";
+            }
+
+            void printResultType( Colour colour, std::string passOrFail ) const {
+                if( !passOrFail.empty() ) {
+                    {
+                        Colour colourGuard( colour );
+                        stream << " " << passOrFail;
+                    }
+                    stream << ":";
+                }
+            }
+
+            void printIssue( std::string issue ) const {
+                stream << " " << issue;
+            }
+
+            void printExpressionWas() {
+                if( result.hasExpression() ) {
+                    stream << ";";
+                    {
+                        Colour colour( dimColour() );
+                        stream << " expression was:";
+                    }
+                    printOriginalExpression();
+                }
+            }
+
+            void printOriginalExpression() const {
+                if( result.hasExpression() ) {
+                    stream << " " << result.getExpression();
+                }
+            }
+
+            void printReconstructedExpression() const {
+                if( result.hasExpandedExpression() ) {
+                    {
+                        Colour colour( dimColour() );
+                        stream << " for: ";
+                    }
+                    stream << result.getExpandedExpression();
+                }
+            }
+
+            void printMessage() {
+                if ( itMessage != messages.end() ) {
+                    stream << " '" << itMessage->message << "'";
+                    ++itMessage;
+                }
+            }
+
+            void printRemainingMessages( Colour colour = dimColour() ) {
+                if ( itMessage == messages.end() )
+                    return;
+
+                // using messages.end() directly yields compilation error:
+                std::vector<MessageInfo>::const_iterator itEnd = messages.end();
+                const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
+
+                {
+                    Colour colourGuard( colour );
+                    stream << " with " << pluralise( N, "message" ) << ":";
+                }
+
+                for(; itMessage != itEnd; ) {
+                    // If this assertion is a warning ignore any INFO messages
+                    if( printInfoMessages || itMessage->type != ResultWas::Info ) {
+                        stream << " '" << itMessage->message << "'";
+                        if ( ++itMessage != itEnd ) {
+                            Colour colourGuard( dimColour() );
+                            stream << " and";
+                        }
+                    }
+                }
+            }
+
+        private:
+            std::ostream& stream;
+            AssertionStats const& stats;
+            AssertionResult const& result;
+            std::vector<MessageInfo> messages;
+            std::vector<MessageInfo>::const_iterator itMessage;
+            bool printInfoMessages;
+        };
+
+        // Colour, message variants:
+        // - white: No tests ran.
+        // -   red: Failed [both/all] N test cases, failed [both/all] M assertions.
+        // - white: Passed [both/all] N test cases (no assertions).
+        // -   red: Failed N tests cases, failed M assertions.
+        // - green: Passed [both/all] N tests cases with M assertions.
+
+        std::string bothOrAll( std::size_t count ) const {
+            return count == 1 ? "" : count == 2 ? "both " : "all " ;
+        }
+
+        void printTotals( const Totals& totals ) const {
+            if( totals.testCases.total() == 0 ) {
+                stream << "No tests ran.";
+            }
+            else if( totals.testCases.failed == totals.testCases.total() ) {
+                Colour colour( Colour::ResultError );
+                const std::string qualify_assertions_failed =
+                    totals.assertions.failed == totals.assertions.total() ?
+                        bothOrAll( totals.assertions.failed ) : "";
+                stream <<
+                    "Failed " << bothOrAll( totals.testCases.failed )
+                              << pluralise( totals.testCases.failed, "test case"  ) << ", "
+                    "failed " << qualify_assertions_failed <<
+                                 pluralise( totals.assertions.failed, "assertion" ) << ".";
+            }
+            else if( totals.assertions.total() == 0 ) {
+                stream <<
+                    "Passed " << bothOrAll( totals.testCases.total() )
+                              << pluralise( totals.testCases.total(), "test case" )
+                              << " (no assertions).";
+            }
+            else if( totals.assertions.failed ) {
+                Colour colour( Colour::ResultError );
+                stream <<
+                    "Failed " << pluralise( totals.testCases.failed, "test case"  ) << ", "
+                    "failed " << pluralise( totals.assertions.failed, "assertion" ) << ".";
+            }
+            else {
+                Colour colour( Colour::ResultSuccess );
+                stream <<
+                    "Passed " << bothOrAll( totals.testCases.passed )
+                              << pluralise( totals.testCases.passed, "test case"  ) <<
+                    " with "  << pluralise( totals.assertions.passed, "assertion" ) << ".";
+            }
+        }
+    };
+
+    INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
+
+} // end namespace Catch
+
+namespace Catch {
+    NonCopyable::~NonCopyable() {}
+    IShared::~IShared() {}
+    StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
+    IContext::~IContext() {}
+    IResultCapture::~IResultCapture() {}
+    ITestCase::~ITestCase() {}
+    ITestCaseRegistry::~ITestCaseRegistry() {}
+    IRegistryHub::~IRegistryHub() {}
+    IMutableRegistryHub::~IMutableRegistryHub() {}
+    IExceptionTranslator::~IExceptionTranslator() {}
+    IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
+    IReporter::~IReporter() {}
+    IReporterFactory::~IReporterFactory() {}
+    IReporterRegistry::~IReporterRegistry() {}
+    IStreamingReporter::~IStreamingReporter() {}
+    AssertionStats::~AssertionStats() {}
+    SectionStats::~SectionStats() {}
+    TestCaseStats::~TestCaseStats() {}
+    TestGroupStats::~TestGroupStats() {}
+    TestRunStats::~TestRunStats() {}
+    CumulativeReporterBase::SectionNode::~SectionNode() {}
+    CumulativeReporterBase::~CumulativeReporterBase() {}
+
+    StreamingReporterBase::~StreamingReporterBase() {}
+    ConsoleReporter::~ConsoleReporter() {}
+    CompactReporter::~CompactReporter() {}
+    IRunner::~IRunner() {}
+    IMutableContext::~IMutableContext() {}
+    IConfig::~IConfig() {}
+    XmlReporter::~XmlReporter() {}
+    JunitReporter::~JunitReporter() {}
+    TestRegistry::~TestRegistry() {}
+    FreeFunctionTestCase::~FreeFunctionTestCase() {}
+    IGeneratorInfo::~IGeneratorInfo() {}
+    IGeneratorsForTest::~IGeneratorsForTest() {}
+
+    Matchers::Impl::StdString::Equals::~Equals() {}
+    Matchers::Impl::StdString::Contains::~Contains() {}
+    Matchers::Impl::StdString::StartsWith::~StartsWith() {}
+    Matchers::Impl::StdString::EndsWith::~EndsWith() {}
+
+    void Config::dummy() {}
+
+    INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#endif
+
+#ifdef CATCH_CONFIG_MAIN
+// #included from: internal/catch_default_main.hpp
+#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
+
+#ifndef __OBJC__
+
+// Standard C/C++ main entry point
+int main (int argc, char * const argv[]) {
+    return Catch::Session().run( argc, argv );
+}
+
+#else // __OBJC__
+
+// Objective-C entry point
+int main (int argc, char * const argv[]) {
+#if !CATCH_ARC_ENABLED
+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+#endif
+
+    Catch::registerTestMethods();
+    int result = Catch::Session().run( argc, (char* const*)argv );
+
+#if !CATCH_ARC_ENABLED
+    [pool drain];
+#endif
+
+    return result;
+}
+
+#endif // __OBJC__
+
+#endif
+
+#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
+#  undef CLARA_CONFIG_MAIN
+#endif
+
+//////
+
+// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
+#ifdef CATCH_CONFIG_PREFIX_ALL
+
+#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
+#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "CATCH_REQUIRE_FALSE" )
+
+#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
+#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
+#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
+
+#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
+#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" )
+#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
+#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
+#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
+
+#define CATCH_CHECK_THROWS( expr )  INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
+#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
+#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
+
+#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
+#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
+
+#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
+#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
+#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
+#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
+#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+    #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
+    #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
+    #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
+    #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+    #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
+    #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
+#else
+    #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
+    #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
+    #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
+    #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
+    #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
+    #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
+#endif
+#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
+
+#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
+#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
+
+#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
+
+// "BDD-style" convenience wrappers
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
+#else
+#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
+#endif
+#define CATCH_GIVEN( desc )    CATCH_SECTION( "Given: " desc, "" )
+#define CATCH_WHEN( desc )     CATCH_SECTION( " When: " desc, "" )
+#define CATCH_AND_WHEN( desc ) CATCH_SECTION( "  And: " desc, "" )
+#define CATCH_THEN( desc )     CATCH_SECTION( " Then: " desc, "" )
+#define CATCH_AND_THEN( desc ) CATCH_SECTION( "  And: " desc, "" )
+
+// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
+#else
+
+#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
+#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" )
+
+#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
+#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
+#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
+
+#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
+#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" )
+#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
+#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
+#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
+
+#define CHECK_THROWS( expr )  INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
+#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
+#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
+
+#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
+#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
+
+#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
+#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
+#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
+#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
+#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+    #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
+    #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
+    #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
+    #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+    #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
+    #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
+#else
+    #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
+    #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
+    #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
+    #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
+    #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
+    #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
+#endif
+#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
+
+#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
+#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
+
+#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
+
+#endif
+
+#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
+
+// "BDD-style" convenience wrappers
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
+#else
+#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
+#endif
+#define GIVEN( desc )    SECTION( "   Given: " desc, "" )
+#define WHEN( desc )     SECTION( "    When: " desc, "" )
+#define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
+#define THEN( desc )     SECTION( "    Then: " desc, "" )
+#define AND_THEN( desc ) SECTION( "     And: " desc, "" )
+
+using Catch::Detail::Approx;
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
diff --git a/testsuite/unittests/catch/test_ag.cc b/testsuite/unittests/catch/test_ag.cc
new file mode 100644
index 0000000..ef27eb2
--- /dev/null
+++ b/testsuite/unittests/catch/test_ag.cc
@@ -0,0 +1,167 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
+#define CATCH_CONFIG_NO_VARIADIC_MACROS
+#include "music/application_graph.hh"
+#include <string>
+
+#include "catch.hpp"
+/*#define CATCH_CONFIG_RUNNER
+ #include <mpi.h>
+ int main( int argc, char* argv[] )
+ {
+ MPI_Init(&argc, &argv);
+
+ int result = Catch::Session().run( argc, argv );
+
+ MPI_Finalize();
+
+ return result;
+ }*/
+using namespace MUSIC;
+typedef AGraph<std::string, char> T_AGraph;
+typedef ANode<std::string, char> T_ANode;
+typedef AEdge<std::string, char> T_AEdge;
+
+class TC_AGraph : public T_AGraph
+{
+protected:
+  int c_loops_;
+public:
+  TC_AGraph() :
+      T_AGraph(1, 2, 1), c_loops_(0)
+  {
+  }
+  ;
+protected:
+  void
+  handleLoop(T_ANode &x, std::vector<T_AEdge> & path)
+  {
+    c_loops_++;
+    T_AGraph::handleLoop(x, path);
+  }
+  void
+  reset()
+  {
+    c_loops_ = 0;
+    T_AGraph::reset();
+
+  }
+};
+
+TEST_CASE_METHOD(TC_AGraph, "Create AGraph with nAppls = 2; nEdges = 1, color = 1", "[agraph]" )
+{
+
+  REQUIRE( n_apps_ == 2);
+  REQUIRE( c_apps_ == 0);
+  REQUIRE( n_edges_ == 1);
+  REQUIRE( c_edges_ == 0);
+  REQUIRE( color_ == 1);
+  REQUIRE( nNodes() == c_apps_);
+  REQUIRE(nEdges() == c_edges_);
+  REQUIRE(local_node_color() == color_);
+
+  bool edge_ = 1;
+  std::string data1("node1");
+  std::string data2("node2");
+  addNode(T_ANode(edge_, !edge_, data1), color_);
+  addNode(T_ANode(!edge_, edge_, data2), color_ - 1);
+  SECTION( "TEST TemporalNegotiatorGraph::addNode()", "[agraph]" )
+    {
+      REQUIRE( c_apps_ == 2);
+    }
+
+  T_ANode &node1 = at(color_);
+  T_ANode &node2 = at(color_ - 1);
+  SECTION( "TEST TemporalNegotiatorGraph::at()", "[agraph]" )
+    {
+      REQUIRE( &(node1.data()) == &data1);
+      REQUIRE(&(node2.data()) == &data2);
+    }
+  SECTION( "TEST TemporalNegotiatorGraph::local_node()", "[agraph]" )
+    {
+      T_ANode &lnode = local_node();
+      REQUIRE( &lnode == &node1);
+    }
+
+  SECTION( "TEST TemporalNegotiatorGraph::iterator", "[agraph]" )
+    {
+      iterator it;
+      int k = 1; //nodes are stored in the order according to the color
+      for (it = begin(); it < end(); ++it, ++k)
+        REQUIRE((it->data()[4] - 48) == (k % 2 + 1));
+    }
+
+  T_AEdge &cur_edge = addEdge(T_AEdge(node1, node2, data1[4]));
+  SECTION( "TEST TemporalNegotiatorGraph::addEdge()", "[agraph]" )
+    {
+      REQUIRE( c_edges_ == 1);
+      REQUIRE(&(cur_edge.data()) == &data1[4]);
+      T_ANode::edge_iterator it;
+      int c_edges = 0;
+      for (it = node1.begin_o(); it < node1.end_o(); ++it, ++c_edges)
+        {
+          REQUIRE( &((*it)->pre()) == &node1);
+          REQUIRE( &((*it)->post()) == &node2);
+        }
+      REQUIRE(c_edges == 1);
+      for (it = node2.begin_o(); it < node2.end_o(); ++it)
+        {
+          REQUIRE(false);
+        }
+      for (it = node1.begin_i(); it < node1.end_i(); ++it)
+        {
+          REQUIRE(false);
+        }
+      c_edges = 0;
+      for (it = node2.begin_i(); it < node2.end_i(); ++it, ++c_edges)
+        {
+          REQUIRE( &((*it)->pre()) == &node1);
+          REQUIRE( &((*it)->post()) == &node2);
+        }
+      REQUIRE(c_edges == 1);
+    }
+  SECTION( "TEST TemporalNegotiatorGraph::edge()", "[agraph]" )
+    {
+      T_AEdge tmp_edge = edge(node1, 0);
+      REQUIRE( &tmp_edge.data() == &data1[4]);
+    }
+  std::vector<T_AEdge> path;
+  depthFirst(node1, path);
+  //very poor check
+  SECTION( "TEST TemporalNegotiatorGraph::depthFirst()", "[agraph]" )
+    {
+      REQUIRE(c_loops_ == 0);
+      iterator it;
+      for (it = begin(); it < end(); ++it)
+        REQUIRE(it->visited);
+
+    }
+
+  reset();
+  SECTION( "TEST TemporalNegotiatorGraph::reset()", "[agraph]" )
+    {
+      iterator it;
+      for (it = begin(); it < end(); ++it)
+        REQUIRE_FALSE(it->visited);
+
+      for (it = begin(); it < end(); ++it)
+        REQUIRE_FALSE(it->in_path);
+    }
+
+}
diff --git a/utils/.gitignore b/utils/.gitignore
new file mode 100644
index 0000000..0559222
--- /dev/null
+++ b/utils/.gitignore
@@ -0,0 +1,15 @@
+/Makefile
+/Makefile.in
+/TAGS
+/.deps
+/core
+/eventcounter
+/eventgenerator
+/eventselect
+/eventsink
+/eventsource
+/music
+/viewevents
+/contsink
+/eventlogger
+/messagesource
diff --git a/utils/ChangeLog b/utils/ChangeLog
new file mode 100644
index 0000000..cd5ef0b
--- /dev/null
+++ b/utils/ChangeLog
@@ -0,0 +1,187 @@
+2012-09-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventgenerator.cc, eventsink.cc: Take options --out and -in for
+	assigning the output and input port names, respectively.
+
+2012-08-23  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventsource.cc: Take option --out for assigning the output port
+	name.
+
+2012-08-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* VisualiseNeurons.cpp: Added #include <unistd.h>.
+
+2011-03-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* application_mapper.cc, application_mapper.hh, music.cc: Added an
+	option -e to the music launcher tool.  This option causes the
+	music launcher tool to write down one launcher script for each
+	application.  These scripts can be used in place of the music tool
+	in environments which require this.
+
+2010-07-28  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.7
+
+2009-10-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.6
+
+2009-10-24  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.5
+
+	* application_mapper.cc (ApplicationMapper::mapConnectivity): Let
+	port code be unique within the multi-simulation.
+
+2009-04-01  Mikael Djurfeldt  <djurfeldt@nada.kth.se>
+
+	* Release 1.0.4
+
+2009-03-13  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.3
+
+2009-03-12  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.2
+
+2009-03-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0.1
+
+2009-03-07  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* VisualiseNeurons.cpp (VisualiseNeurons::printHelp): Updated text.
+
+	* eventcounter.cc (usage): Updated text.
+
+2009-03-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music.cc: New option -v.
+
+2009-03-04  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music.cc (print_map): New function.
+	(main): Add new option -m for printing of application ranks.
+
+2009-03-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Release 1.0
+
+2009-02-15  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* application_mapper.cc (ApplicattionMapper::mapConnectivity):
+	Moved generation of port codes to a position which is treated
+	identically in all processes.
+
+2009-02-11  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music.cc: Moved mpi dependent code to ../mpidep/mpidep.cc.
+
+	* Makefile.am: Removed dependency on librudeconfig for all
+	utilities except the music launcher.
+
+	* Makefile.am (music_LDADD): Added dependency on libmpidep.a.
+
+	* music.cc: Test if ompi_comm_free exists instead of
+	ompi_comm_create which doesn't exist in OpenMPI 1.3.
+
+2009-02-10  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventcounter.cc, eventsource.cc, eventgenerator: Added option
+	--maxbuffered.
+
+	* music.cc (getRank): Added code to support newer (1.3.x) versions
+	of OpenMPI.
+
+2009-02-05  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* application_mapper.cc (ApplicationMapper::mapConnectivity):
+	Compute and propagate a unique "port code" for each port name.
+
+2008-12-02  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Switch to CamelCase.
+	
+2008-11-16  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am: Added eventcounter.
+
+	* eventcounter.cc: New file.
+
+2008-11-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* VisualiseNeurons.cpp: #include <cstring>.  (Should change to C++
+	code.)
+
+	* music.cc (launch): Added standard configuration variable "wd",
+	specifying working directory.
+
+2008-11-05  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventgenerator.cc: New file.
+
+	* Makefile.am: Added eventgenerator.cc.
+
+2008-11-03  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventsink.cc, eventselect.cc: New files.
+
+	* Makefile.am: Added eventsink, eventselect.
+
+	* eventsource.cc: Error checking when opening files.
+
+	* Makefile.am: Compile viewevents conditionally.
+
+2008-11-02  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventsource.cc: Extended to support global and local indices and
+	roundrobin index maps.
+
+2008-10-30  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Changes to implement propagation of configuration
+	information and routing of spikes.
+
+2008-10-10  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventsource.cc: Updated to use global_index.
+
+2008-10-08  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* eventsource.cc, datafile.h, datafile.cc: New files.
+
+	* Makefile.am: Added eventsource.
+
+2007-11-06  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* music.cc (BGL): #include <rts.h>
+
+2007-11-02  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* application_map.hh: #include "rudeconfig/src/config.h" instead
+	of <rude/config.h>.
+
+	* Makefile.am (music_CXXFLAGS): Added -I$(top_srcdir).
+
+	* music.cc (get_rank): Support OPENMPI.
+
+2007-11-01  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* parse.hh, parse.cc: Moved to src.
+
+	* music.cc: Rewritten.
+
+	* Makefile.am (music_SOURCES): Added application_map.hh,
+	application_map.cc.
+
+2007-10-25  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Makefile.am, music.cc, parse.cc, parse.hh: New files.
+
+2007-08-17  Mikael Djurfeldt  <mikael@djurfeldt.com>
+
+	* Pang!
+
diff --git a/utils/Makefile.am b/utils/Makefile.am
new file mode 100644
index 0000000..8d157ab
--- /dev/null
+++ b/utils/Makefile.am
@@ -0,0 +1,54 @@
+## Process this file with Automake to create Makefile.in
+
+ACLOCAL = $(top_srcdir)/aclocal.sh
+
+bin_PROGRAMS = music @MPI_UTILS@ @OPTIONAL_UTILS@
+
+EXTRA_PROGRAMS = eventsource eventsink eventselect \
+				eventgenerator eventcounter eventlogger \
+				contsink messagesource viewevents
+
+MUSIC_INCLUDE = -I$(top_srcdir)/src -I$(top_builddir)/src
+
+ music_SOURCES = music.cc
+ music_CXXFLAGS = $(MUSIC_INCLUDE) -I$(top_srcdir) @MPI_CXXFLAGS@
+ music_LDADD = $(top_builddir)/src/libmusic.la $(top_builddir)/mpidep/libmpidep.la @MPI_LDFLAGS@
+
+ eventsource_SOURCES = eventsource.cc datafile.h datafile.cc
+ eventsource_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+ eventsource_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+ eventsink_SOURCES = eventsink.cc
+ eventsink_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+ eventsink_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+ eventselect_SOURCES = eventselect.cc
+ eventselect_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+ eventselect_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+ eventgenerator_SOURCES = eventgenerator.cc
+ eventgenerator_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+ eventgenerator_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+ eventcounter_SOURCES = eventcounter.cc
+ eventcounter_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+ eventcounter_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+ eventlogger_SOURCES = eventlogger.cc
+ eventlogger_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+ eventlogger_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+ contsink_SOURCES = contsink.cc
+ contsink_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+ contsink_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+ messagesource_SOURCES = messagesource.cc
+ messagesource_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+ messagesource_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@
+
+ viewevents_SOURCES = viewevents.cpp VisualiseNeurons.cpp VisualiseNeurons.h
+ viewevents_CXXFLAGS = $(MUSIC_INCLUDE) @MPI_CXXFLAGS@
+ viewevents_LDADD = $(top_builddir)/src/libmusic.la @MPI_LDFLAGS@  -lglut -lGL -lGLU 
+
+
+MKDEP = gcc -M $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
diff --git a/utils/VisualiseNeurons.cpp b/utils/VisualiseNeurons.cpp
new file mode 100644
index 0000000..ea2d09b
--- /dev/null
+++ b/utils/VisualiseNeurons.cpp
@@ -0,0 +1,631 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// VisualiseNeurons.cpp written by Johannes Hjorth, hjorth@nada.kth.se
+
+
+#include "VisualiseNeurons.h"
+
+#include <unistd.h>
+
+void VisualiseNeurons::printHelp() {
+  std::cerr << "Usage: viewevents [OPTION...] CONFIGFILE" << std::endl
+	    << "`viewevents' receives spikes through a MUSIC input port" << std::endl
+	    << "and displays them as a 3D graphical representation." << std::endl << std::endl
+	    << "  -t, --timestep TIMESTEP time between tick() calls (default 1 ms)" << std::endl
+	    << "  -s, --scaletime SCALING real time to simulated time scale factor (s)" << std::endl
+	    << "                          If omitted, the visualisation runs at full speed." << std::endl
+	    << "  -h, --help              print this help message" << std::endl
+	    << "  -T, --title TITLE       window title" << std::endl << std::endl
+            << "CONFIGFILE format:" << std::endl
+            << "<Number of neuron types (1 int)>" << std::endl
+  << "<Baseline colour neuron 1 (3 double): R G B>" << std::endl
+  << "<Excited colour neuron 1 (3 double): R G B>" << std::endl
+  << "[Baseline colour neuron i: R G B]" << std::endl
+  << "[Excited colour neuron i: R G B]" << std::endl
+  << "<Neuron 1 information (4 double, 1 int): X Y Z RADIE NEURONTYPEINDEX>" << std::endl
+  << "[Neuron i information: X Y Z RADIE NEURONTYPEINDEX]" << std::endl << std::endl
+	    << "Report bugs to <music-bugs@incf.org>." << std::endl;
+  exit(1);
+}
+
+void VisualiseNeurons::getArgs(int argc, char* argv[]) {
+
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option long_options[] =
+	{
+	  {"timestep",  required_argument, 0, 't'},
+	  {"scaletime",  required_argument, 0, 's'},
+	  {"help",      no_argument,       0, 'h'},
+          {"title", required_argument, 0, 'T'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:s:T:h", long_options, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  dt_ = atof (optarg); //*fixme* error checking
+          std::cout << "Using dt = " << dt_ << std::endl;
+	  continue;
+	case 's':
+          synchFlag_ = 1;
+          scaleTime_ = atof(optarg);
+          std::cout << "Using scaletime: " << scaleTime_ << std::endl;
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+        case 'T':
+          windowTitle_ = optarg; //new string(optarg);
+          continue;
+	case 'h':
+          printHelp(); 
+          // fall through...
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind + 1 || argc > optind + 1) {
+    printHelp(); // exits
+  }
+
+  confFile_ = string(argv[optind]);
+
+}
+
+
+void VisualiseNeurons::run(int argc, char **argv) {
+
+  // Add this object to the static-wrapper
+  objTable_.push_back(this);
+
+  // Init music
+  setup_ = new MUSIC::Setup(argc, argv);
+  MPI::Intracomm comm = setup_->communicator();
+  rank_ = comm.Get_rank(); 
+
+  if(rank_ > 0) {
+    std::cerr << argv[0] << " only supports one process currently!" 
+              << std::endl;
+    exit(-1);
+  }
+
+  // Init glut
+  glutInit(&argc,argv);
+  glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
+
+
+  // Store the stop time
+  setup_->config ("stoptime", &stopTime_);
+
+  // Parse inparameters
+  getArgs(argc,argv);
+
+  readConfigFile(confFile_);
+
+  MUSIC::EventInputPort* evport = setup_->publishEventInput("plot");
+
+
+  if (!evport->isConnected()) {
+    if (rank_ == 0)
+      std::cerr << "port `plot' is not connected" << std::endl;
+    comm.Abort (1);
+  }
+
+  if(evport->width() != (int) coords_.size()) {
+    std::cerr << "Size mismatch: port width " << evport->width()
+              << " number of neurons to plot " << coords_.size()
+              << std::endl;
+  }
+
+
+  MUSIC::LinearIndex indexmap(0, evport->width());
+  evport->map (&indexmap, this, 0.0);
+
+  double stoptime;
+  setup_->config ("stoptime", &stoptime);
+  
+
+  // GLUT
+  glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
+  glutInitWindowSize(500, 500);
+  glutInitWindowPosition(50, 50);
+  glutCreateWindow(windowTitle_.c_str());
+
+  // Initialise
+  glEnable(GL_DEPTH_TEST);
+  glClearColor (0.0,0.0,0.0,1.0);
+
+  GLfloat pos[4] = { -100, 100, 200, 0.0 };
+  GLfloat light[4] = { 1.0, 1.0, 1.0, 1.0};
+
+  // Lightsources
+  glLightfv(GL_LIGHT0, GL_POSITION, pos);
+  glLightfv(GL_LIGHT0, GL_DIFFUSE,  light);
+  glLightfv(GL_LIGHT0, GL_SPECULAR, light);
+  glEnable(GL_LIGHT0);
+  glEnable(GL_LIGHTING);
+
+  // Default materials
+  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+  glEnable(GL_COLOR_MATERIAL);
+  glEnable(GL_NORMALIZE);
+
+  // Setup camera
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  double fov = (is3dFlag_) ? 0.7*maxDist_/2 : 0.5*maxDist_/2;
+
+  // std::cout << "MAX DIST: " << maxDist_ << std::endl;
+  glFrustum(-fov,fov,-fov,fov,maxDist_/2,3.1*maxDist_); // Visible range 50-800
+  glTranslated(0,0,-2.2*maxDist_); //-600
+
+  double camAng = (is3dFlag_) ? 30 : -30;
+  glRotated(camAng,1,0,0);
+  glMatrixMode(GL_MODELVIEW);
+
+  // Create displaylist for neuron(s)
+  GLUquadric* neuronQuad = gluNewQuadric();
+
+  int nVert = (coords_.size() < 500) ? 10 : 2;
+
+  neuronList_ = glGenLists(1);
+
+  glNewList(neuronList_, GL_COMPILE);
+  gluSphere(neuronQuad, 1, nVert*2, nVert);
+  //gluSphere(neuronQuad, 1, 20, 10);
+  glEndList();
+
+  glutDisplayFunc(displayWrapper);
+
+  glutPostRedisplay();
+  glFinish();
+
+
+
+  // Music done.
+
+
+  if(rank_ == 0) {
+    void *exitStatus;
+
+    glutTimerFunc(25,rotateTimerWrapper, 1);    
+
+    pthread_create(&tickThreadID_, NULL, runMusic, &synchFlag_);
+
+    glutPostRedisplay();
+    glFinish();
+
+    glutMainLoop();
+    pthread_join(tickThreadID_,&exitStatus);
+
+  } else {
+    std::cerr << "Only run start() on rank 0" << std::endl;
+  }
+
+}
+
+void VisualiseNeurons::finalize() {
+  runtime_->finalize ();
+
+  delete runtime_;
+
+  //  std::cout << "Rank " << rank_ 
+  //          << ": Searching for VisualiseNeurons wrapper object";
+  for(unsigned int i = 0; i < objTable_.size(); i++) {
+    if(objTable_[i] == this) {
+      //std::cout << "found.";
+    }
+    else {
+      //std::cout << ".";
+    }
+  }
+  //std::cout << std::endl;
+
+  // Should delete all other objects also.
+
+}
+
+
+void VisualiseNeurons::display() {
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glLoadIdentity();
+  glRotated(rotAngle_,0.1*sin(rotAngle_/100),1,0);
+
+  for(unsigned int i = 0; i < coords_.size(); i++) {
+    // Here we translate coordinate system and draw a neuron
+    glPushMatrix();
+
+    //double vMin = -100e-3;
+    //double vMax = 100e-3;
+
+    double col = volt_[i]; //(volt_[i] - vMin)/(vMax - vMin);
+
+    // maxCol is [1 0.9 0]
+    //    GLdouble red =   0.25 + 0.75*col;
+    //    GLdouble green = 0.53 + 0.37*col;
+    //    GLdouble blue =  0.10 - 0.10*col;
+    neuronColour tmpColB = baseLineCol_[cMap_[i]];
+    neuronColour tmpColE = excitedCol_[cMap_[i]];
+
+    GLdouble red   = tmpColB.r + (tmpColE.r-tmpColB.r)*col;
+    GLdouble green = tmpColB.g + (tmpColE.g-tmpColB.g)*col;
+    GLdouble blue  = tmpColB.b + (tmpColE.b-tmpColB.b)*col;
+
+    glColor3d(red,green,blue);
+    //float specReflection[] = { 0.2*col, 0.2*col, 0.2*col, 1 };
+    //glMaterialfv(GL_FRONT, GL_SPECULAR, specReflection);
+
+    glTranslated(coords_[i].x,coords_[i].y,coords_[i].z);
+
+    double scale = coords_[i].r*(1+spikeScale_*col);
+    glScaled(scale,scale,scale);
+    glCallList(neuronList_);
+    glPopMatrix();
+  }
+
+  char buffer[20];
+
+  sprintf(buffer,"%.3f s",time_);
+  //std::cout << "Buffer: " << buffer << std::endl;
+  //std::cout << time_ << std::endl;
+
+  glLoadIdentity();
+  glColor3d(0.2,0.2,0.4);
+  //  glRasterPos2d(-maxDist_*1.7,-maxDist_*1.75);
+  //  glRasterPos3d(-maxDist_*2,-1.7*maxDist_,0*maxDist_);
+  if(is3dFlag_) {
+    glColor3d(1,1,1);
+    glRasterPos3d(-maxDist_*0.9,-maxDist_*0.5,maxDist_);
+  }
+  else {
+    glRasterPos3d(-maxDist_*0.8,maxDist_*0.8,0.3*maxDist_);
+  }
+  for(unsigned int i = 0; i < strlen(buffer); i++) {
+    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,buffer[i]);
+  }
+
+  glutSwapBuffers();
+
+}
+
+
+
+void VisualiseNeurons::addNeuron(double x, double y, double z, double r, double cIdx) {
+
+  if(cIdx >= cMap_.size()) {
+    std::cerr << "VisualiseNeurons: Neuron colour index "
+              << cIdx << " out of range, using 0." << std::endl;
+    cIdx = 0;
+  }
+
+  // std::cout << "Adding neuron " << x << "," << y << "," << z 
+  //          << "," << r << "," << cIdx << std::endl;
+
+  neuronCoord p;
+  p.x = x; p.y = y; p.z = z; p.r = r;
+  coords_.push_back(p);
+  volt_.push_back(0);
+  cMap_.push_back(cIdx);
+}
+
+void VisualiseNeurons::rotateTimer() {
+  rotAngle_ += 0.5;
+
+  if(rotAngle_ >= 36000) {
+    rotAngle_ -= 36000;
+  }
+
+}
+
+void VisualiseNeurons::operator () (double t, MUSIC::GlobalIndex id) {
+  //std::cout << "Event " << id << " detected at " << t 
+  //          << " (vis time = " << time_ << ")" <<  std::endl;
+
+  assert(0 <= id && id < (int) volt_.size()); // Check that it is within range
+
+  if(t < time_) // time_ is old timestep
+    {
+      std::cerr << "Received old spike " << t << " at " << time_ << std::endl;
+    }
+
+  TimeIdPair *tmpPair = new TimeIdPair(t,id);
+
+  // Add time to priority queue
+  priorityQueue_.push(*tmpPair);
+  
+}
+
+
+void VisualiseNeurons::tick() {
+
+  if(!done_){
+
+    // Reinitialize realtime clock at first tick
+    if (runtime_->time () == 0.0)
+      gettimeofday(&tickStartTime_,NULL);
+
+
+#if 0
+    // Call music to get the latest simulation data
+    std::cerr << "Size: " << volt_.size() << " ";
+    std::cerr << "Entering tick (" << time_ <<")...";
+#endif
+
+    runtime_->tick();
+
+#if 0
+    std::cerr << "done(" << time_ <<")." << std::endl;
+#endif    
+
+
+    oldTime_ = time_;
+    time_ = runtime_->time ();
+
+    // Make sure the time steps are correct
+    assert(dt_ - 1e-9 < time_ - oldTime_ 
+           && time_ - oldTime_ < dt_ + 1e-9);
+
+
+    // Should we make the visualisation go in realTime=scaleTime_*simTime?
+    if(synchFlag_) {
+      // Yes, how long did we spend in the tick?
+      gettimeofday(&tickEndTime_,NULL);
+
+      // How much of the time allocated for this timestep remains?
+      double delayLeft = dt_*scaleTime_ 
+        - (tickEndTime_.tv_sec - tickStartTime_.tv_sec)
+        - (tickEndTime_.tv_usec - tickStartTime_.tv_usec) / 1000000.0;
+
+
+      if(delayLeft > 0) {        
+
+        // We reuse the timeval for the delay
+        tickDelay_.tv_sec = 0;
+        tickDelay_.tv_usec = (int) (delayLeft*1e6);
+
+        //        std::cerr << "Delay left : " << tickDelay_.tv_usec 
+        //                  << " milliseconds" << std::endl;
+
+        // Delay so that enough time passes
+        //select(0,0,0,0,&tickDelay_);
+        usleep(tickDelay_.tv_usec);
+
+
+      } else {
+        // Whoops, simulation were too slow... print error.
+        std::cerr << "t = " << time_ 
+                  << ": Music's tick() took "
+                  << -delayLeft*1e6 << " microseconds too long to execute" 
+                  << std::endl;
+
+      }
+
+      // Set end of this tick as start of next tick
+      gettimeofday(&tickStartTime_,NULL);
+    }
+    
+
+    // Decay the volt/activity
+    for(unsigned int i = 0; i < volt_.size(); i++) {
+      volt_[i] *= 1-(time_-oldTime_)/tau_;
+    }
+
+    // Add any new spikes that occured since last tick()
+    while(!priorityQueue_.empty() && priorityQueue_.top().getTime() <= time_) 
+      {
+        volt_[priorityQueue_.top().getId()] = 1;
+        priorityQueue_.pop();
+
+      }
+
+
+    // Tell GLUT to update the screen
+    //glutPostRedisplay();
+
+    // Have we reached the end?
+    if(time_ >= stopTime_ - dt_/2.0) {
+      done_ = 1;
+    }
+  } else {
+    std::cout << "Last tick." << std::endl;
+  }
+
+}
+
+
+void VisualiseNeurons::displayWrapper() {
+  for(unsigned int i = 0; i < objTable_.size(); i++) {
+    VisualiseNeurons *vn = objTable_[i];
+    vn->display();
+  }
+}
+
+void VisualiseNeurons::rotateTimerWrapper(int v) {
+  VisualiseNeurons *vn = 0;
+
+  for(unsigned int i = 0; i < objTable_.size(); i++) {
+    vn = objTable_[i];
+    if(vn->is3dFlag_) {    
+      vn->rotateTimer();
+    }
+  }
+
+  glutPostRedisplay();
+  glFinish();
+
+  if(vn && !(vn->done_)) {
+    glutTimerFunc(100,rotateTimerWrapper, 1);
+  }
+}
+
+
+
+void* VisualiseNeurons::runMusic(void *arg) {
+  VisualiseNeurons *vn = 0;
+
+  for(unsigned int i = 0; i < objTable_.size(); i++) {
+    vn = objTable_[i];
+    
+    // Switch to runtime mode
+    // If the code is extended to handle more than one process
+    // then this will actually be SLOWER since the runtimes 
+    // are *not* created in parallell
+
+    // Reason for this current setup is that we want to start
+    // the GLUT-loop as fast as possible, to get something on screen.
+    vn->runtime_ = new MUSIC::Runtime (vn->setup_, vn->dt_);
+
+  }
+
+  int allDone = 0;
+
+
+  while(!allDone && objTable_.size() > 0) {
+
+    allDone = 1;
+
+    for(unsigned int i = 0; i < objTable_.size(); i++) {
+      vn = objTable_[i];
+      vn->tick();
+
+      if(vn && !vn->done_) {
+        allDone = 0;
+      }
+    }
+  }
+
+  std::cout << "Simulation done." << std::endl;
+
+  // Simulation done.
+  glutLeaveMainLoop();
+
+  // Thread ends, return null
+  return NULL;
+
+
+}
+
+
+void VisualiseNeurons::readConfigFile(string filename) {
+  double x, y, z, r, dist;
+  double minDist = 1e66, maxR = 0;
+
+  neuronColour tmp;
+  int i = 0;
+  int nCols, cIdx;
+
+  std::cout << "Reading : " << filename << std::endl;
+
+  Datafile in(filename);
+
+  if (!in) {
+    std::cerr << "eventsource: could not open "
+              << filename << std::endl;
+    abort ();
+  }
+
+
+  // !!! WHY?!!
+  // VisualiseNeurons.cpp:246: undefined reference to `datafile::skip_header()'
+  //in.skip_header();
+
+  // How many different colours are there
+  in >> nCols;
+  std::cout << "VisualiseNeurons: Reading " << nCols 
+            << " different neuron types" << std::endl;
+
+  for(i = 0; i < nCols; i++) { 
+    // Read in neuron base colours
+    in >> tmp.r >> tmp.g >> tmp.b;
+    baseLineCol_.push_back(tmp);
+
+    // Read in neuron excited colour
+    in >> tmp.r >> tmp.g >> tmp.b;
+    excitedCol_.push_back(tmp);
+  }
+
+
+  // Read in neuron coordinates and colour
+  in >> x >> y >> z >> r >> cIdx;
+  
+
+  while(!in.eof()) {
+    addNeuron(x,y,z,r,cIdx);
+    dist = sqrt(x*x + y*y + z*z);
+    maxDist_ = (dist > maxDist_) ? dist : maxDist_;
+
+    // All neurons are not in one plane
+    if(abs(x) > 1e-9 && abs(y) > 1e-9 && abs(z) > 1e-9) {
+      is3dFlag_ = 1;
+    }
+
+
+    // Dist and R are used to calculate spikeScale_    
+    if(dist > 0) {
+      minDist = (dist < minDist) ? dist : minDist;
+    }
+
+    maxR = (r > maxR) ? r : maxR;
+
+    // std::cout << "Neuron " << i << " at " << x << "," << y << "," << z 
+    //           << " radie " << r << std::endl;
+    i++;
+
+    // Read in neuron coordinates and colour index
+    in >> x >> y >> z >> r >> cIdx;
+
+  }
+
+  spikeScale_ = (minDist/(3*maxR))-1;
+  spikeScale_ = (spikeScale_ > 0) ? spikeScale_ : 0;
+
+  std::cout << "Read " << i << " neuron positions" << std::endl;
+  std::cout << "Setting spike scaling to " << spikeScale_ << std::endl;
+}
+
+
+/*
+bool VisualiseNeurons::TimeIdPair::operator<(const TimeIdPair& right) const
+{
+  return time_ < right.getTime();
+}
+*/
+
+ //bool VisualiseNeurons::TimeIdPair::operator>(const TimeIdPair& right) const
+bool TimeIdPair::operator<(const TimeIdPair& right) const
+{
+
+  // Note that we use > here, since we want lowest items first
+  return time_ > right.getTime();
+}
+
+
diff --git a/utils/VisualiseNeurons.h b/utils/VisualiseNeurons.h
new file mode 100644
index 0000000..79bd360
--- /dev/null
+++ b/utils/VisualiseNeurons.h
@@ -0,0 +1,177 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// VisualiseNeurons.h written by Johannes Hjorth, hjorth@nada.kth.se
+
+
+#include <GL/gl.h>
+#include <GL/freeglut.h>
+#include <math.h>
+#include <mpi.h>
+#include <music.hh>
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include "datafile.h"
+#include <assert.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <getopt.h>
+#include <string.h>
+#include <vector>
+#include <queue>
+
+#ifndef _VISUALISE_NEURONS
+#define _VISUALISE_NEURONS
+
+#define DEFAULT_TIMESTEP 1e-3
+#define PI 3.141592653589793
+
+
+  // Inner class used in priority queue
+  class TimeIdPair
+  {
+  public:
+
+    TimeIdPair() { time_ = -1; };
+    TimeIdPair(double time, MUSIC::GlobalIndex id) { time_ = time; id_ = id; }
+
+    //bool operator<(const TimeIdPair&) const;
+    bool operator<(const TimeIdPair&) const;
+
+    double getTime() const { return time_; }
+    MUSIC::GlobalIndex getId() const { return id_; }
+
+  private:
+    double time_;
+    MUSIC::GlobalIndex id_;
+  };
+
+
+
+class VisualiseNeurons : public MUSIC::EventHandlerGlobalIndex {
+
+ public:
+  VisualiseNeurons() {
+    tau_ = 10e-3;      // How fast does activity decay in visualisation?
+    time_ = 0;         // Current time
+    dt_ = DEFAULT_TIMESTEP;
+    stopTime_ = 0;     // End of simulation time
+    oldTime_ = 0;      // Time of previous timestep
+    done_ = 0;         // Are we there yet?
+
+    maxDist_ = 0;      // Radie of a thought sphere containing all neurons
+    is3dFlag_ = 0;     // If it is 3d structure, then lets rotate.
+
+    synchFlag_ = 0;    // Should we try to keep a steady pace or go full speed?
+    scaleTime_ = 1;
+
+    gettimeofday(&tickStartTime_,NULL);
+    windowTitle_ = "viewevents";
+  }
+  
+  void run(int argc, char **argv);
+  void readConfigFile(string filename);
+  void finalize();
+
+  // Event handler for incomming spikes
+  void operator () ( double t, MUSIC::GlobalIndex id );
+
+  void display();
+  void rotateTimer();
+  void tick();
+
+  void addNeuron(double x, double y, double z, double r, double cIdx);
+
+  // Static wrapper functions
+  static void displayWrapper();
+  static void rotateTimerWrapper(int v);
+  static void* runMusic(void *arg);
+
+  typedef struct {
+    GLdouble x;
+    GLdouble y;
+    GLdouble z;
+    GLdouble r; // radie of neuron
+  }neuronCoord;
+
+  typedef struct {
+    GLdouble r;
+    GLdouble g;
+    GLdouble b;
+  }neuronColour;
+
+
+
+ private:
+
+  void getArgs(int argc, char* argv[]);
+  void printHelp();
+
+  MUSIC::Setup* setup_;     // ONLY to be used during setup phase
+  MUSIC::Runtime* runtime_; // Music runtime object
+  
+  GLuint neuronList_;  // OpenGL list for drawing object
+
+  std::vector<neuronCoord> coords_;  // Coordinates of neuron population
+  std::vector<double> volt_;  // Activity of neuron population
+  std::vector<int> cMap_;   // Which colour does neurons have 
+
+  std::vector<neuronColour> baseLineCol_;  // Colour of resting neuron
+  std::vector<neuronColour> excitedCol_;   // Colour of spiking neuron
+  double spikeScale_;         // eg, 0.1 = scale up spiking neurons by 10%
+
+  string windowTitle_; 
+
+  double dt_;
+  double tau_;       // Tau decay of activity
+  double time_;      // Current time
+  double oldTime_;   // Previous timestep
+  double stopTime_;  // End of simulations
+  int done_;         // Simulation done?
+
+  double rotAngle_;  // Current rotation angle
+
+  int rank_;         // Rank of this process
+
+  double maxDist_;   // Distance from origo to outermost neuron
+                     // Used when calculating camera position
+
+  int is3dFlag_;
+
+  pthread_t tickThreadID_;
+
+  int synchFlag_;    // Do we try to synch, or run full throttle?
+  double scaleTime_; // real time / simulated time
+  struct timeval tickStartTime_;
+  struct timeval tickEndTime_;
+  struct timeval tickDelay_;
+
+
+  string confFile_;  // Config file with colours and coordinates
+
+  //priority_queue <TimeIdPair> priorityQueue_;
+  std::priority_queue<TimeIdPair> priorityQueue_;
+};
+
+static std::vector<VisualiseNeurons*> objTable_;
+
+
+
+#endif 
diff --git a/utils/contsink.cc b/utils/contsink.cc
new file mode 100644
index 0000000..dcfdad8
--- /dev/null
+++ b/utils/contsink.cc
@@ -0,0 +1,135 @@
+#include <mpi.h>
+#include <music.hh>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <cstdlib>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#define DEFAULT_TIMESTEP 1e-2
+
+double *data;
+
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: contsink [OPTION...]" << std::endl
+		<< "`contsink' receives continuous data" << std::endl
+		<< "through a MUSIC input port." << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -d, --delay SECS        delay until data should arrive" << std::endl
+		<< "  -i, --interpolate       no interpolation" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+double timestep = DEFAULT_TIMESTEP;
+double delay = 0.0;
+bool   interpolate = true;
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",    required_argument, 0, 't'},
+	  {"delay",       required_argument, 0, 'd'},
+	  {"interpolate", no_argument,       0, 'i'},
+	  {"help",        no_argument,       0, 'h'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:d:ih",
+			   longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg);
+	  continue;
+	case 'd':
+	  delay = atof (optarg);
+	  continue;
+	case 'i':
+	  interpolate = false;
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind + 0 || argc > optind + 0)
+    usage (rank);
+}
+
+int
+main (int argc, char* argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+
+  MUSIC::ContInputPort* contdata = setup->publishContInput ("contdata");
+
+  MPI::Intracomm comm = setup->communicator ();
+  int nProcesses = comm.Get_size ();
+  int rank = comm.Get_rank ();
+
+  getargs (rank, argc, argv);
+
+  int totalWidth = contdata->width ();
+  int localWidth = (totalWidth-1) / nProcesses + 1;
+  int myWidth = localWidth;
+  if (rank == nProcesses - 1)	// Last processor
+    myWidth = totalWidth - (nProcesses-1) * localWidth;
+
+  data = new double[myWidth];
+
+  // Declare where in memory to put data
+  MUSIC::ArrayData dmap (data,
+			 MPI::DOUBLE,
+			 rank * localWidth,
+			 myWidth);
+  contdata->map (&dmap, delay, interpolate);
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+
+  for (; runtime->time () < stoptime; runtime->tick ())
+    {
+      for (int i = 0; i < myWidth; ++i)
+	std::cout << data[i] << " ";
+      std::cout << "on " << rank << " @" << runtime->time () << std::endl;
+    }
+
+  runtime->finalize ();
+  
+  delete runtime;
+
+  return 0;
+}
diff --git a/utils/datafile.cc b/utils/datafile.cc
new file mode 100644
index 0000000..74114b8
--- /dev/null
+++ b/utils/datafile.cc
@@ -0,0 +1,99 @@
+/* This file is part of the skol suite.
+   Copyright (C) 2005, 2008 Mikael Djurfeldt
+
+   The skol suite 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; either version 3, or (at
+   your option) any later version.
+
+   The skol suite 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 should have received a copy of the GNU General Public License
+   along with the skol suite; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+
+#include <iostream>
+#include <limits>
+#include <cctype>
+
+#include "datafile.h"
+
+using std::numeric_limits;
+
+bool
+Datafile::atHeaderLine ()
+{
+  return peek () == '#';
+}
+
+void
+Datafile::ignoreLine ()
+{
+  ignore (numeric_limits<int>::max (), '\n');
+}
+
+void
+Datafile::ignoreWhitespace ()
+{
+  while (isspace (peek ()))
+    ignore ();
+}
+
+bool
+Datafile::scanLine (const char* pattern)
+{
+  const char* p = pattern;
+  while (*p != '\0')
+    {
+      if (peek () == '\n')
+	{
+	  ignore ();
+	  return false;
+	}
+      if (peek () == *p)
+	++p;
+      else
+	p = pattern;
+      ignore ();
+    }
+  return true;
+}
+
+bool
+Datafile::read (const char* pattern, int& x)
+{
+  seekg (0);
+  while (atHeaderLine ())
+    if (scanLine (pattern))
+      {
+	*this >> x;
+	return true;
+      }
+  return false;
+}
+
+bool
+Datafile::read (const char* pattern, double& x)
+{
+  seekg (0);
+  while (atHeaderLine ())
+    if (scanLine (pattern))
+      {
+	*this >> x;
+	return true;
+      }
+  return false;
+}
+
+void
+Datafile::skipHeader ()
+{
+  ignoreWhitespace ();
+  while (atHeaderLine ())
+    ignoreLine ();
+}
diff --git a/utils/datafile.h b/utils/datafile.h
new file mode 100644
index 0000000..d1894f9
--- /dev/null
+++ b/utils/datafile.h
@@ -0,0 +1,38 @@
+/* This file is part of the skol suite.
+   Copyright (C) 2005, 2008, 2009 Mikael Djurfeldt
+
+   The skol suite 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; either version 3, or (at
+   your option) any later version.
+
+   The skol suite 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 should have received a copy of the GNU General Public License
+   along with the skol suite; see the file COPYING.  If not, write to
+   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+
+#ifndef DATAFILE_H
+
+#include <string>
+#include <fstream>
+
+class Datafile : public std::ifstream {
+ protected:
+  bool atHeaderLine ();
+  bool scanLine (const char* pattern);
+ public:
+  Datafile (std::string filename) : std::ifstream (filename.data ()) { }
+  void ignoreLine ();
+  void ignoreWhitespace ();
+  bool read (const char*, int& x);
+  bool read (const char*, double& x);
+  void skipHeader ();
+};
+#define DATAFILE_H
+#endif
diff --git a/utils/eventcounter.cc b/utils/eventcounter.cc
new file mode 100644
index 0000000..506c780
--- /dev/null
+++ b/utils/eventcounter.cc
@@ -0,0 +1,224 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <vector>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+const double DEFAULT_TIMESTEP = 1e-2;
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: eventcounter [OPTION...] N_UNITS PREFIX [SUFFIX]" << std::endl
+		<< "`eventcounter' receives spikes through a MUSIC input port, counts" << std::endl
+		<< "all spikes for each index and writes the frequencies to a set of files" << std::endl
+		<< "with names PREFIX RANK SUFFIX" << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -b, --maxbuffered TICKS maximal amount of data buffered" << std::endl
+		<< "  -m, --imaptype TYPE     linear (default) or roundrobin" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+std::vector<int> counters;
+
+class MyEventHandlerLocal: public MUSIC::EventHandlerLocalIndex {
+public:
+  void operator () (double t, MUSIC::LocalIndex id)
+  {
+    ++counters[id];
+  }
+};
+
+int nUnits;
+double timestep = DEFAULT_TIMESTEP;
+int    maxbuffered = 0;
+string imaptype = "linear";
+string prefix;
+string suffix = ".dat";
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",  required_argument, 0, 't'},
+	  {"maxbuffered", required_argument, 0, 'b'},
+	  {"imaptype",  required_argument, 0, 'm'},
+	  {"help",      no_argument,       0, 'h'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:b:m:h", longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg); // NOTE: could do error checking
+	  continue;
+	case 'b':
+	  maxbuffered = atoi (optarg);
+	  continue;
+	case 'm':
+	  imaptype = optarg;
+	  if (imaptype != "linear" && imaptype != "roundrobin")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind + 2 || argc > optind + 3)
+    usage (rank);
+
+  nUnits = atoi (argv[optind]);
+  prefix = argv[optind + 1];
+  if (argc == optind + 3)
+    suffix = argv[optind + 2];
+}
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  
+  MPI::Intracomm comm = setup->communicator ();
+  int nProcesses = comm.Get_size ();
+  int rank = comm.Get_rank ();
+  
+  getargs (rank, argc, argv);
+
+  MUSIC::EventInputPort* in = setup->publishEventInput ("in");
+  if (!in->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "eventcounter port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  std::ostringstream spikefile;
+  spikefile << prefix << rank << suffix;
+  std::ofstream out (spikefile.str ().c_str ());
+  if (!out)
+    {
+      std::cerr << "eventcounter: could not open "
+		<< spikefile.str () << " for writing" << std::endl;
+      abort ();      
+    }
+
+  MyEventHandlerLocal evhandlerLocal;
+  
+  if (imaptype == "linear")
+    {
+      int nUnitsPerProcess = nUnits / nProcesses;
+      int nLocalUnits = nUnitsPerProcess;
+      int rest = nUnits % nProcesses;
+      int firstId = nUnitsPerProcess * rank;
+      if (rank < rest)
+	{
+	  firstId += rank;
+	  nLocalUnits += 1;
+	}
+      else
+	firstId += rest;
+      MUSIC::LinearIndex indices (firstId, nLocalUnits);
+
+      if (maxbuffered > 0)
+	in->map (&indices, &evhandlerLocal, 0.0, maxbuffered);
+      else
+	in->map (&indices, &evhandlerLocal, 0.0);
+    }
+  else
+    {
+      std::vector<MUSIC::GlobalIndex> v;
+      for (int i = rank; i < nUnits; i += nProcesses)
+	v.push_back (i);
+      MUSIC::PermutationIndex indices (&v.front (), v.size ());
+
+      if (maxbuffered > 0)
+	in->map (&indices, &evhandlerLocal, 0.0, maxbuffered);
+      else
+	in->map (&indices, &evhandlerLocal, 0.0);
+    }
+
+  counters.resize (nUnits);
+  for (int i = 0; i < nUnits; ++i)
+    counters[i] = 0;
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  double time = runtime->time ();
+  while (time < stoptime)
+    {
+      // Retrieve data from other program
+      runtime->tick ();
+      
+      time = runtime->time ();
+    }
+  for (std::vector<int>::iterator i = counters.begin ();
+       i != counters.end ();
+       ++i)
+    out << static_cast<double> (*i) / stoptime << std::endl;
+  out.close ();
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/utils/eventgenerator.cc b/utils/eventgenerator.cc
new file mode 100644
index 0000000..75d854e
--- /dev/null
+++ b/utils/eventgenerator.cc
@@ -0,0 +1,256 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <cstdlib>
+#include <cmath>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+#include "datafile.h"
+
+const double DEFAULT_TIMESTEP = 1e-2;
+const double DEFAULT_FREQUENCY = 10.0; // Hz
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: eventgenerator [OPTION...] N_UNITS" << std::endl
+		<< "`eventgenerator' generates spikes from a Poisson distribution." << std::endl << std:: endl
+		<< "  -t, --timestep  TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -b, --maxbuffered TICKS  maximal amount of data buffered" << std::endl
+		<< "  -f, --frequency FREQ     average frequency (default " << DEFAULT_FREQUENCY << " Hz)" << std::endl
+		<< "  -m, --imaptype  TYPE     linear (default) or roundrobin" << std::endl
+		<< "  -i, --indextype TYPE     global (default) or local" << std::endl
+		<< "      --out PORTNAME       output port name (default: out)" << std::endl
+		<< "  -h, --help               print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+string portName ("out");
+int nUnits;
+double timestep = DEFAULT_TIMESTEP;
+int    maxbuffered = 0;
+double freq = DEFAULT_FREQUENCY;
+string imaptype = "linear";
+string indextype = "global";
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  enum { OUT };
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",  required_argument, 0, 't'},
+	  {"maxbuffered", required_argument, 0, 'b'},
+	  {"frequency", required_argument, 0, 'f'},
+	  {"imaptype",  required_argument, 0, 'm'},
+	  {"indextype", required_argument, 0, 'i'},
+	  {"help",      no_argument,       0, 'h'},
+	  {"out",	  required_argument, 0, OUT},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:b:f:m:i:h", longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg); // NOTE: could do error checking
+	  continue;
+	case 'b':
+	  maxbuffered = atoi (optarg);
+	  continue;
+	case 'f':
+	  freq = atof (optarg); // NOTE: error checking here as well
+	  continue;
+	case 'm':
+	  imaptype = optarg;
+	  if (imaptype != "linear" && imaptype != "roundrobin")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case 'i':
+	  indextype = optarg;
+	  if (indextype != "global" && indextype != "local")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case OUT:
+	  portName = optarg;
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc != optind + 1)
+    usage (rank);
+
+  nUnits = atoi (argv[optind]);
+}
+
+double
+negexp (double m)
+{
+  return - m * log (drand48 ());
+}
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  
+  MPI::Intracomm comm = setup->communicator ();
+  int nProcesses = comm.Get_size ();
+  int rank = comm.Get_rank ();
+  
+  getargs (rank, argc, argv);
+
+  MUSIC::EventOutputPort* out = setup->publishEventOutput (portName);
+  if (!out->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "eventgenerator port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  MUSIC::Index::Type type;
+  if (indextype == "global")
+    type = MUSIC::Index::GLOBAL;
+  else
+    type = MUSIC::Index::LOCAL;
+  
+  std::vector<MUSIC::GlobalIndex> ids;
+  std::vector<double> nextSpike;
+  
+  if (imaptype == "linear")
+    {
+      int nUnitsPerProcess = nUnits / nProcesses;
+      int nLocalUnits = nUnitsPerProcess;
+      int rest = nUnits % nProcesses;
+      int firstId = nUnitsPerProcess * rank;
+      if (rank < rest)
+	{
+	  firstId += rank;
+	  nLocalUnits += 1;
+	}
+      else
+	firstId += rest;
+      for (int i = 0; i < nLocalUnits; ++i)
+	ids.push_back (firstId + i);
+      MUSIC::LinearIndex indices (firstId, nLocalUnits);
+      
+      if (maxbuffered > 0)
+	out->map (&indices, type, maxbuffered);
+      else
+	out->map (&indices, type);
+    }
+  else
+    {
+      for (int i = rank; i < nUnits; i += nProcesses)
+	ids.push_back (i);
+      MUSIC::PermutationIndex indices (&ids.front (), ids.size ());
+      if (maxbuffered > 0)
+	out->map (&indices, type, maxbuffered);
+      else
+	out->map (&indices, type);
+    }
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  srand48 (rank);		// Use different seeds
+
+  double m = 1.0 / freq;
+  for (unsigned int i = 0; i < ids.size (); ++i)
+    nextSpike.push_back (negexp (m));
+
+  double time = runtime->time ();
+  while (time < stoptime)
+    {
+      double nextTime = time + timestep;
+
+      if (type == MUSIC::Index::GLOBAL)
+	{
+	  for (unsigned int i = 0; i < ids.size (); ++i)
+	    while (nextSpike[i] < nextTime)
+	      {
+		out->insertEvent (nextSpike[i],
+				  MUSIC::GlobalIndex (ids[i]));
+		nextSpike[i] += negexp (m);
+	      }
+	}
+      else
+	{
+	  for (unsigned int i = 0; i < ids.size (); ++i)
+	    while (nextSpike[i] < nextTime)
+	      {
+		out->insertEvent (nextSpike[i],
+				  MUSIC::LocalIndex (i));
+		nextSpike[i] += negexp (m);
+	      }
+	}
+      
+      // Make data available for other programs
+      runtime->tick ();
+
+      time = runtime->time ();
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/utils/eventlogger.cc b/utils/eventlogger.cc
new file mode 100644
index 0000000..c2f6812
--- /dev/null
+++ b/utils/eventlogger.cc
@@ -0,0 +1,271 @@
+#include <mpi.h>
+#include <cstdlib>
+#include <iostream>
+#include <music.hh>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+const double DEFAULT_TIMESTEP = 0.01;
+
+MPI::Intracomm comm;
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: eventlogger [OPTION...]" << std::endl
+		<< "`eventlogger' logs spikes from a MUSIC port." << std::endl << std::endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -l, --acclatency LATENCY acceptable data latency (s)" << std::endl
+		<< "  -b, --maxbuffered TICKS maximal amount of data buffered" << std::endl
+		<< "  -m, --imaptype TYPE     linear (default) or roundrobin" << std::endl
+		<< "  -i, --indextype TYPE    global (default) or local" << std::endl
+		<< "  -a, --all               each receiver rank reports all spikes" << std::endl
+		<< "      --in PORTNAME       input port name (default: in)" << std::endl
+		<< "      --message-in PORTNAME message port name (default: message)" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+double apptime;
+
+class MyEventHandlerGlobal : public MUSIC::EventHandlerGlobalIndex {
+  int rank;
+public:
+  MyEventHandlerGlobal (int rank_) : rank (rank_) { }
+  void operator () (double t, MUSIC::GlobalIndex id)
+  {
+    // For now: just print out incoming events
+    std::cout << "Rank " << rank
+	      << ": Event (" << id << ", " << t
+	      << ") detected at " << apptime << std::endl;
+  }
+};
+
+class MyEventHandlerLocal: public MUSIC::EventHandlerLocalIndex {
+  int rank;
+public:
+  MyEventHandlerLocal (int rank_) : rank (rank_) { }
+  void operator () (double t, MUSIC::LocalIndex id)
+  {
+    // For now: just print out incoming events
+    std::cout << "Rank " << rank
+	      << ": Event (" << id << ", " << t
+	      << ") detected at " << apptime << std::endl;
+  }
+};
+
+class MyMessageHandler : public MUSIC::MessageHandler {
+  int rank;
+public:
+  MyMessageHandler (int rank_) : rank (rank_) { }
+  void operator () (double t, void* msg, size_t size)
+  {
+    // Print out incoming messages
+    std::string message (static_cast<char*> (msg), size);
+    std::cout << "Rank " << rank
+	      << ": Message (" << t << ", " << message
+	      << ") detected at " << apptime << std::endl;
+  }
+};
+
+string portName ("in");
+string messagePortName ("message");
+double timestep = DEFAULT_TIMESTEP;
+double latency = 0.0;
+int    maxbuffered = 0;
+std::string imaptype = "linear";
+std::string indextype = "global";
+bool all = false;
+
+int
+main (int argc, char* argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  comm = setup->communicator ();
+  int nProcesses = comm.Get_size (); // how many processes are there?
+  int rank = comm.Get_rank ();        // which process am I?
+
+  enum { IN, MESSAGE_IN };
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",  required_argument, 0, 't'},
+	  {"acclatency", required_argument, 0, 'l'},
+	  {"maxbuffered", required_argument, 0, 'b'},
+	  {"imaptype",  required_argument, 0, 'm'},
+	  {"indextype", required_argument, 0, 'i'},
+	  {"all",	no_argument,	   0, 'a'},
+	  {"help",      no_argument,       0, 'h'},
+	  {"in",	required_argument, 0, IN},
+	  {"message-in", required_argument, 0, MESSAGE_IN},
+	  {0, 0, 0, 0}
+	};
+       //`getopt_long' stores the option index here.
+      int optionIndex = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:l:b:m:i:ah", longOptions, &optionIndex);
+
+     //  detect the end of the options
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg); // NOTE: could add error checking
+	  continue;
+	case 'l':
+	  latency = atof (optarg);
+	  continue;
+	case 'b':
+	  maxbuffered = atoi (optarg);
+	  continue;
+	case 'm':
+	  imaptype = optarg;
+	  if (imaptype != "linear" && imaptype != "roundrobin")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case 'i':
+	  indextype = optarg;
+	  if (indextype != "global" && indextype != "local")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case 'a':
+	  all = true;
+	  continue;
+	case IN:
+	  portName = optarg;
+	  continue;
+	case MESSAGE_IN:
+	  messagePortName = optarg;
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  // Port publishing
+  MUSIC::EventInputPort* evport = setup->publishEventInput (portName);
+  MUSIC::MessageInputPort* msgport = setup->publishMessageInput (messagePortName);
+  if (!evport->isConnected () && !msgport->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "eventlogger: no connected input ports" << std::endl;
+      comm.Abort (1);
+    }
+
+  // Port mapping
+
+  MyEventHandlerGlobal evhandlerGlobal (rank);
+  MyEventHandlerLocal evhandlerLocal (rank);
+
+  if (evport->isConnected ())
+    {
+      // Split the width among the available processes
+      int width = 0;
+      if (evport->hasWidth ())
+	width = evport->width ();
+      else
+	{
+	  std::cerr << "port width not specified in Configuration file"
+		    << std::endl;
+	  comm.Abort (1);
+	}
+
+      if (imaptype == "linear")
+	{
+	  int nLocal = width / nProcesses;
+	  int rest = width % nProcesses;
+	  int firstId = nLocal * rank;
+	  if (rank < rest)
+	    {
+	      firstId += rank;
+	      nLocal += 1;
+	    }
+	  else
+	    firstId += rest;
+	  MUSIC::LinearIndex indexmap (all ? 0 : firstId,
+				       all ? width : nLocal);
+      
+	  if (indextype == "global")
+	    if (maxbuffered > 0)
+	      evport->map (&indexmap, &evhandlerGlobal, latency, maxbuffered);
+	    else
+	      evport->map (&indexmap, &evhandlerGlobal, latency);
+	  else
+	    if (maxbuffered > 0)
+	      evport->map (&indexmap, &evhandlerLocal, latency, maxbuffered);
+	    else
+	      evport->map (&indexmap, &evhandlerLocal, latency);
+	}
+      else
+	{
+	  std::vector<MUSIC::GlobalIndex> v;
+	  for (int i = all ? 0 : rank; i < width; i += all ? 1 : nProcesses)
+	    v.push_back (i);
+	  MUSIC::PermutationIndex indexmap (&v.front (), v.size ());
+      
+	  if (indextype == "global")
+	    if (maxbuffered > 0)
+	      evport->map (&indexmap, &evhandlerGlobal, latency, maxbuffered);
+	    else
+	      evport->map (&indexmap, &evhandlerGlobal, latency);
+	  else
+	    if (maxbuffered > 0)
+	      evport->map (&indexmap, &evhandlerLocal, latency, maxbuffered);
+	    else
+	      evport->map (&indexmap, &evhandlerLocal, latency);
+	}
+    }
+
+  // Messages
+  MyMessageHandler msgHandler (rank);
+  if (msgport->isConnected ())
+    {
+      if (maxbuffered > 0)
+	msgport->map (&msgHandler, latency, maxbuffered);
+      else
+	msgport->map (&msgHandler, latency);
+    }
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  // Run
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  apptime = runtime->time ();
+  while (apptime < stoptime)
+    {
+      // Retrieve data from other program
+      runtime->tick ();
+
+      apptime = runtime->time ();
+    }
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/utils/eventselect.cc b/utils/eventselect.cc
new file mode 100644
index 0000000..28ce97e
--- /dev/null
+++ b/utils/eventselect.cc
@@ -0,0 +1,246 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <vector>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+const double DEFAULT_TIMESTEP = 1e-2;
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: eventselect [OPTION...] N_UNITS UNITS" << std::endl
+		<< "`eventselect' receives events from an input port of width N_UNITS" << std::endl
+		<< "and sends events for the subset of id:s specified in the file UNITS" << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+std::vector<MUSIC::Event> eventBuffer;
+
+class MyEventHandlerGlobal : public MUSIC::EventHandlerGlobalIndex {
+public:
+  void operator () (double t, MUSIC::GlobalIndex id)
+  {
+    eventBuffer.push_back (MUSIC::Event (t, id));
+  }
+};
+
+int nUnits;
+double timestep = DEFAULT_TIMESTEP;
+string units;
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",  required_argument, 0, 't'},
+	  {"help",      no_argument,       0, 'h'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:m:i:h", longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg); // NOTE: some error checking would be good!
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc != optind + 2)
+    usage (rank);
+
+  nUnits = atoi (argv[optind]);
+  units = argv[optind + 1];
+}
+
+void
+mapOutput (MUSIC::EventOutputPort* out,
+	   int nProcesses,
+	   int rank,
+	   std::string fname)
+{
+  std::ifstream unitfile (fname.c_str ());
+  if (!unitfile)
+    {
+      std::cerr << "eventselect: could not open "
+		<< fname << " for writing" << std::endl;
+      abort ();      
+    }
+
+  // First count the integers
+  int nUnits = 0;
+  int id;
+  while (unitfile >> id)
+    ++nUnits;
+  unitfile.close ();
+  int nUnitsPerProcess = nUnits / nProcesses;
+  int nLocalUnits = nUnitsPerProcess;
+  int rest = nUnits % nProcesses;
+  int firstId = nUnitsPerProcess * rank;
+  if (rank < rest)
+    {
+      firstId += rank;
+      nLocalUnits += 1;
+    }
+  else
+    firstId += rest;
+  // Now read in our selection
+  nUnits = 0;
+  unitfile.open (fname.c_str ());
+  while (nUnits < firstId)
+    {
+      unitfile >> id;
+      ++nUnits;
+    }
+  nUnits = 0;
+  std::vector<MUSIC::GlobalIndex> units;
+  while (nUnits < nLocalUnits)
+    {
+      unitfile >> id;
+      units.push_back (id);
+      ++nUnits;
+    }
+  unitfile.close ();
+  MUSIC::PermutationIndex indices (&units.front (), units.size ());
+
+  out->map (&indices, MUSIC::Index::GLOBAL);
+}
+
+void
+mapInput (MUSIC::EventInputPort* in,
+	  int nProcesses,
+	  int rank,
+	  MyEventHandlerGlobal& evhandler)
+{
+  int nUnitsPerProcess = nUnits / nProcesses;
+  int nLocalUnits = nUnitsPerProcess;
+  int rest = nUnits % nProcesses;
+  int firstId = nUnitsPerProcess * rank;
+  if (rank < rest)
+    {
+      firstId += rank;
+      nLocalUnits += 1;
+    }
+  else
+    firstId += rest;
+  MUSIC::LinearIndex indices (firstId, nLocalUnits);
+
+  in->map (&indices, &evhandler, 0.0);
+}
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  
+  MPI::Intracomm comm = setup->communicator ();
+  int nProcesses = comm.Get_size ();
+  int rank = comm.Get_rank ();
+  
+  getargs (rank, argc, argv);
+
+  MUSIC::EventInputPort* in = setup->publishEventInput ("in");
+  if (!in->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "eventselect port in is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  MUSIC::EventOutputPort* out = setup->publishEventOutput ("out");
+  if (!out->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "eventselect port out is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  mapOutput (out, nProcesses, rank, units);
+
+  MyEventHandlerGlobal evhandlerGlobal;
+
+  mapInput (in, nProcesses, rank, evhandlerGlobal);
+  
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  double time = runtime->time ();
+  while (time < stoptime)
+    {
+      eventBuffer.clear ();
+      // Retrieve data
+      runtime->tick ();
+      
+      sort (eventBuffer.begin (), eventBuffer.end ());
+      for (std::vector<MUSIC::Event>::iterator i = eventBuffer.begin ();
+	   i != eventBuffer.end ();
+	   ++i)
+	// Send data (NOTE: assumes that non-mapped id:s will be discarded)
+	out->insertEvent (i->t, MUSIC::GlobalIndex (i->id));
+
+      time = runtime->time ();
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/utils/eventsink.cc b/utils/eventsink.cc
new file mode 100644
index 0000000..7f55782
--- /dev/null
+++ b/utils/eventsink.cc
@@ -0,0 +1,243 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <vector>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+const double DEFAULT_TIMESTEP = 1e-2;
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: eventsink [OPTION...] N_UNITS PREFIX [SUFFIX]" << std::endl
+		<< "`eventsink' receives spikes through a MUSIC input port" << std::endl
+		<< "and writes these to a set of files with names PREFIX RANK SUFFIX" << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -m, --imaptype TYPE     linear (default) or roundrobin" << std::endl
+		<< "  -i, --indextype TYPE    global (default) or local" << std::endl
+		<< "      --in PORTNAME       input port name (default: in)" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+std::vector<MUSIC::Event> eventBuffer;
+
+class MyEventHandlerGlobal : public MUSIC::EventHandlerGlobalIndex {
+public:
+  void operator () (double t, MUSIC::GlobalIndex id)
+  {
+    eventBuffer.push_back (MUSIC::Event (t, id));
+  }
+};
+
+class MyEventHandlerLocal: public MUSIC::EventHandlerLocalIndex {
+public:
+  void operator () (double t, MUSIC::LocalIndex id)
+  {
+    eventBuffer.push_back (MUSIC::Event (t, id));
+  }
+};
+
+string portName ("in");
+int nUnits;
+double timestep = DEFAULT_TIMESTEP;
+string imaptype = "linear";
+string indextype = "global";
+string prefix;
+string suffix = ".dat";
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  enum { IN };
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",  required_argument, 0, 't'},
+	  {"imaptype",  required_argument, 0, 'm'},
+	  {"indextype", required_argument, 0, 'i'},
+	  {"help",      no_argument,       0, 'h'},
+	  {"in",	required_argument, 0, IN},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:m:i:h", longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg); // NOTE: could do error checking
+	  continue;
+	case 'm':
+	  imaptype = optarg;
+	  if (imaptype != "linear" && imaptype != "roundrobin")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case 'i':
+	  indextype = optarg;
+	  if (indextype != "global" && indextype != "local")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case IN:
+	  portName = optarg;
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind + 2 || argc > optind + 3)
+    usage (rank);
+
+  nUnits = atoi (argv[optind]);
+  prefix = argv[optind + 1];
+  if (argc == optind + 3)
+    suffix = argv[optind + 2];
+}
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  
+  MPI::Intracomm comm = setup->communicator ();
+  int nProcesses = comm.Get_size ();
+  int rank = comm.Get_rank ();
+  
+  getargs (rank, argc, argv);
+
+  MUSIC::EventInputPort* in = setup->publishEventInput (portName);
+  if (!in->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "eventsink port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  std::ostringstream spikefile;
+  spikefile << prefix << rank << suffix;
+  std::ofstream out (spikefile.str ().c_str ());
+  if (!out)
+    {
+      std::cerr << "eventsink: could not open "
+		<< spikefile.str () << " for writing" << std::endl;
+      abort ();      
+    }
+
+  MyEventHandlerGlobal evhandlerGlobal;
+  MyEventHandlerLocal evhandlerLocal;
+  
+  if (imaptype == "linear")
+    {
+      int nUnitsPerProcess = nUnits / nProcesses;
+      int nLocalUnits = nUnitsPerProcess;
+      int rest = nUnits % nProcesses;
+      int firstId = nUnitsPerProcess * rank;
+      if (rank < rest)
+	{
+	  firstId += rank;
+	  nLocalUnits += 1;
+	}
+      else
+	firstId += rest;
+      MUSIC::LinearIndex indices (firstId, nLocalUnits);
+
+      if (indextype == "global")
+	in->map (&indices, &evhandlerGlobal, 0.0);
+      else
+	in->map (&indices, &evhandlerLocal, 0.0);
+    }
+  else
+    {
+      std::vector<MUSIC::GlobalIndex> v;
+      for (int i = rank; i < nUnits; i += nProcesses)
+	v.push_back (i);
+      MUSIC::PermutationIndex indices (&v.front (), v.size ());
+
+      if (indextype == "global")
+	in->map (&indices, &evhandlerGlobal, 0.0);
+      else
+	in->map (&indices, &evhandlerLocal, 0.0);
+    }
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  double time = runtime->time ();
+  while (time < stoptime)
+    {
+      eventBuffer.clear ();
+      // Retrieve data from other program
+      runtime->tick ();
+      
+      sort (eventBuffer.begin (), eventBuffer.end ());
+      for (std::vector<MUSIC::Event>::iterator i = eventBuffer.begin ();
+	   i != eventBuffer.end ();
+	   ++i)
+	out << i->t << '\t' << i->id << std::endl;
+
+      time = runtime->time ();
+    }
+  out.close ();
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/utils/eventsource.cc b/utils/eventsource.cc
new file mode 100644
index 0000000..075f062
--- /dev/null
+++ b/utils/eventsource.cc
@@ -0,0 +1,243 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <cstdlib>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+#include "datafile.h"
+
+const double DEFAULT_TIMESTEP = 1e-2;
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: eventsource [OPTION...] N_UNITS PREFIX [SUFFIX]" << std::endl
+		<< "`eventsource' reads spikes from a set of files with names PREFIX RANK SUFFIX" << std::endl
+		<< "and propagates these spikes through a MUSIC output port." << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -b, --maxbuffered TICKS maximal amount of data buffered" << std::endl
+		<< "  -m, --imaptype TYPE     linear (default) or roundrobin" << std::endl
+		<< "  -i, --indextype TYPE    global (default) or local" << std::endl
+		<< "      --out PORTNAME      output port name (default: out)" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+string portName ("out");
+int    nUnits;
+double timestep = DEFAULT_TIMESTEP;
+int    maxbuffered = 0;
+string imaptype = "linear";
+string indextype = "global";
+string prefix;
+string suffix = ".dat";
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  enum { OUT };
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",    required_argument, 0, 't'},
+	  {"maxbuffered", required_argument, 0, 'b'},
+	  {"imaptype",    required_argument, 0, 'm'},
+	  {"indextype",   required_argument, 0, 'i'},
+	  {"help",        no_argument,       0, 'h'},
+	  {"out",	  required_argument, 0, OUT},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:b:m:i:h",
+			   longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg); // NOTE: could do error checking
+	  continue;
+	case 'b':
+	  maxbuffered = atoi (optarg);
+	  continue;
+	case 'm':
+	  imaptype = optarg;
+	  if (imaptype != "linear" && imaptype != "roundrobin")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case 'i':
+	  indextype = optarg;
+	  if (indextype != "global" && indextype != "local")
+	    {
+	      usage (rank);
+	      abort ();
+	    }
+	  continue;
+	case OUT:
+	  portName = optarg;
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind + 2 || argc > optind + 3)
+    usage (rank);
+
+  nUnits = atoi (argv[optind]);
+  prefix = argv[optind + 1];
+  if (argc == optind + 3)
+    suffix = argv[optind + 2];
+}
+
+
+int
+main (int argc, char *argv[])
+{
+
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  
+  MPI::Intracomm comm = setup->communicator ();
+  int nProcesses = comm.Get_size ();
+  int rank = comm.Get_rank ();
+
+
+  getargs (rank, argc, argv);
+
+  MUSIC::EventOutputPort* out = setup->publishEventOutput (portName);
+  if (!out->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "eventsource port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  MUSIC::Index::Type type;
+  if (indextype == "global")
+    type = MUSIC::Index::GLOBAL;
+  else
+    type = MUSIC::Index::LOCAL;
+  
+  if (imaptype == "linear")
+    {
+      int nUnitsPerProcess = nUnits / nProcesses;
+      int nLocalUnits = nUnitsPerProcess;
+      int rest = nUnits % nProcesses;
+      int firstId = nUnitsPerProcess * rank;
+      if (rank < rest)
+	{
+	  firstId += rank;
+	  nLocalUnits += 1;
+	}
+      else
+	firstId += rest;
+      MUSIC::LinearIndex indices (firstId, nLocalUnits);
+
+      if (maxbuffered > 0)
+	out->map (&indices, type, maxbuffered);
+      else
+	out->map (&indices, type);
+    }
+  else
+    {
+      std::vector<MUSIC::GlobalIndex> v;
+      for (int i = rank; i < nUnits; i += nProcesses)
+	v.push_back (i);
+      MUSIC::PermutationIndex indices (&v.front (), v.size ());
+      if (maxbuffered > 0)
+	out->map (&indices, type, maxbuffered);
+      else
+	out->map (&indices, type);
+    }
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  std::ostringstream spikefile;
+  spikefile << prefix << rank << suffix;
+  Datafile in (spikefile.str ());
+  if (!in)
+    {
+      std::cerr << "eventsource: could not open "
+		<< spikefile.str () << std::endl;
+      abort ();      
+    }
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  in.skipHeader ();
+  int id;
+  double t;
+  in >> t >> id;
+  bool moreSpikes = !in.eof ();
+  
+  double time = runtime->time ();
+  while (time < stoptime)
+    {
+      double nextTime = time + timestep;
+      while (moreSpikes && t < nextTime)
+	{
+    	 // MUSIC_LOGR("event("<<id<<","<<t<<")");
+	  out->insertEvent (t, MUSIC::GlobalIndex (id));
+	  in >> t >> id;
+	  moreSpikes = !in.eof ();
+	}
+      // Make data available for other programs
+      runtime->tick ();
+
+      time = runtime->time ();
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/utils/messagesource.cc b/utils/messagesource.cc
new file mode 100644
index 0000000..2735a78
--- /dev/null
+++ b/utils/messagesource.cc
@@ -0,0 +1,177 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// Leave as first include---required by BG/L
+#include <mpi.h>
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <cstdlib>
+#include <cstring>
+
+extern "C" {
+#include <unistd.h>
+#include <getopt.h>
+}
+
+#include <music.hh>
+
+const double DEFAULT_TIMESTEP = 1e-2;
+
+void
+usage (int rank)
+{
+  if (rank == 0)
+    {
+      std::cerr << "Usage: messagesource [OPTION...] PREFIX [SUFFIX]" << std::endl
+		<< "`messagesource' reads messages from a set of files with names PREFIX RANK SUFFIX" << std::endl
+		<< "and propagates these messages through a MUSIC output port." << std::endl << std:: endl
+		<< "  -t, --timestep TIMESTEP time between tick() calls (default " << DEFAULT_TIMESTEP << " s)" << std::endl
+		<< "  -b, --maxbuffered TICKS maximal amount of data buffered" << std::endl
+		<< "  -h, --help              print this help message" << std::endl << std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (1);
+}
+
+double timestep = DEFAULT_TIMESTEP;
+int    maxbuffered = 0;
+string prefix;
+string suffix = ".dat";
+
+void
+getargs (int rank, int argc, char* argv[])
+{
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"timestep",    required_argument, 0, 't'},
+	  {"maxbuffered", required_argument, 0, 'b'},
+	  {"help",        no_argument,       0, 'h'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+t:b:h",
+			   longOptions, &option_index);
+
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 't':
+	  timestep = atof (optarg); // NOTE: could do error checking
+	  continue;
+	case 'b':
+	  maxbuffered = atoi (optarg);
+	  continue;
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  if (argc < optind + 1 || argc > optind + 2)
+    usage (rank);
+
+  prefix = argv[optind];
+  if (argc == optind + 2)
+    suffix = argv[optind + 1];
+}
+
+int
+main (int argc, char *argv[])
+{
+  MUSIC::Setup* setup = new MUSIC::Setup (argc, argv);
+  
+  MPI::Intracomm comm = setup->communicator ();
+  int rank = comm.Get_rank ();
+  
+  getargs (rank, argc, argv);
+
+  MUSIC::MessageOutputPort* out = setup->publishMessageOutput ("out");
+  if (!out->isConnected ())
+    {
+      if (rank == 0)
+	std::cerr << "messagesource port is not connected" << std::endl;
+      comm.Abort (1);
+    }
+
+  if (maxbuffered > 0)
+    out->map (maxbuffered);
+  else
+    out->map ();
+
+  double stoptime;
+  setup->config ("stoptime", &stoptime);
+
+  std::ostringstream messagefile;
+  messagefile << prefix << rank << suffix;
+  std::ifstream in (messagefile.str ().c_str ());
+  if (!in)
+    {
+      std::cerr << "messagesource: could not open "
+		<< messagefile.str () << std::endl;
+      abort ();      
+    }
+
+  MUSIC::Runtime* runtime = new MUSIC::Runtime (setup, timestep);
+
+  double t;
+  char msg[80];
+  in >> t;
+  in.ignore (); // ignore one whitespace character
+  in.get (msg, 80);
+  bool moreMessages = !in.eof ();
+  
+  double time = runtime->time ();
+  while (time < stoptime)
+    {
+      double nextTime = time + timestep;
+      while (moreMessages && t < nextTime)
+	{
+	  out->insertMessage (t, msg, strlen (msg));
+	  in >> t;
+	  in.ignore (); // ignore one whitespace character
+	  in.get (msg, 80);
+	  moreMessages = !in.eof ();
+	}
+      // Make data available for other programs
+      runtime->tick ();
+
+      time = runtime->time ();
+    }
+
+  runtime->finalize ();
+
+  delete runtime;
+
+  return 0;
+}
diff --git a/utils/music.cc b/utils/music.cc
new file mode 100644
index 0000000..a0e2cad
--- /dev/null
+++ b/utils/music.cc
@@ -0,0 +1,262 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2007, 2008, 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string>
+#include <fstream>
+
+#include "config.h"
+
+#include <music/version.hh>
+
+#include "music/application_mapper.hh"
+#include "mpidep/mpidep.hh"
+
+extern "C" {
+#include <sys/types.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+}
+using std::string;
+
+void
+usage (int rank)
+{
+  if (rank <= 0)
+    {
+      std::cout << "Usage: mpirun ... music [OPTION...] CONFIG" << std::endl
+		<< "`music' launches an application as part of a multi-simulation job." << std::endl << std::endl
+		<< "  -h, --help            print this help message" << std::endl
+		<< "  -m, --map             print application rank map" << std::endl
+//		<< "  -f, --file-map        creates a file with the list of environment variable of each application" << std::endl
+//		<< "  -e, --export-scripts  export launcher scripts" << std::endl
+		<< "  -v, --version         prints version of MUSIC library" << std::endl
+		<< std::endl
+		<< "Report bugs to <music-bugs@incf.org>." << std::endl;
+    }
+  exit (0);
+}
+
+
+void
+print_map (MUSIC::Configuration* config)
+{
+  MUSIC::ApplicationMap* a = config->applications ();
+  std::cout << "rank\tapplication" << std::endl;
+  for (MUSIC::ApplicationMap::iterator i = a->begin (); i != a->end (); ++i)
+    {
+      int first = i->leader ();
+      int nProc = i->nProc ();
+      std::cout << first;
+      if (nProc > 1)
+	std::cout << "-" << first + nProc - 1;
+      std::cout << '\t' << i->name () << std::endl;
+    }
+}
+
+/*const static char* const configEnvVarName = "_MUSIC_CONFIG_";
+const static char* const mapFName = "music.map";
+void
+export_scripts (MUSIC::ApplicationMapper* map)
+{
+  MUSIC::Configuration* config = map->config ();
+  MUSIC::ApplicationMap* a = config->applications ();
+  for (MUSIC::ApplicationMap::iterator i = a->begin (); i != a->end (); ++i)
+    {
+      std::string name = i->name ();
+      std::string fname = name + ".sh";
+      std::ofstream script (fname.c_str ());
+      script << "#!/bin/sh" << std::endl << std::endl;
+      map->mapConnectivity (name);
+      MUSIC::Configuration* config = map->config (i->color());
+      config->writeEnv ();
+      script << "export " << configEnvVarName
+	     << "=\"" << getenv (configEnvVarName)
+	     << '"' << std::endl;
+      std::string binary;
+      config->lookup ("binary", &binary);
+      std::string args;
+      config->lookup ("args", &args);
+      script << binary << ' ' << args << std::endl;
+      script.close ();
+    }
+}
+
+void export_map(MUSIC::ApplicationMapper* map)
+{
+	MUSIC::Configuration* config = map->config ();
+	MUSIC::ApplicationMap* a = config->applications ();
+    std::ofstream map_file (mapFName);
+	  for (MUSIC::ApplicationMap::iterator i = a->begin (); i != a->end (); ++i)
+	    {
+		  map->mapConnectivity (i->name());
+		  MUSIC::Configuration* config = map->config (i->color());
+		  config->writeEnv ();
+		  map_file <<  getenv (configEnvVarName) << std::endl;
+	    }
+	  map_file.close ();
+}*/
+
+
+void
+print_version (int rank)
+{
+  if (rank <= 0)
+    {
+      std::cout << "MUSIC " << MUSIC::version () << std::endl
+		<< "Copyright (C) 2007-2012 INCF." << std::endl
+		<< "You may redistribute copies of MUSIC" << std::endl
+		<< "under the terms of the GNU General Public License." << std::endl
+		<< "For more information about these matters, see the file named COPYING." << std::endl;
+    }
+  exit (0);
+}
+
+
+void
+launch (MUSIC::Configuration* config, char** argv)
+{
+  string binary;
+  config->lookup ("binary", &binary);
+  config->writeEnv ();
+  string wd;
+  if (config->lookup ("wd", &wd))
+    {
+      if (chdir (wd.c_str ()))
+	goto error_exit;
+    }
+  execvp (binary.c_str (), argv);
+
+ error_exit:
+  // if we get here, something is wrong
+  std::cerr << "Error during launching of binary " << binary << std::endl;
+  perror ("MUSIC");
+  exit (1);
+}
+
+/* remedius
+ * option -f to the music launcher tool is added.  This option causes the
+ *	music launcher tool to write a file  that contains mapping information of the rank (rank range)
+ *	to the according launching environment variable.
+ *	This file can be used while launching multiple applications in MPMD mode.
+ */
+int
+main (int argc, char *argv[])
+{
+  // predict the rank MPI::Init will give us using
+  // mpi implementation dependent code from ../mpidep
+  int rank = -1;
+#if MUSIC_USE_MPI
+  rank = getRank (argc, argv);
+#endif
+
+  bool do_print_map = false;
+  bool do_export_scripts = false;
+  bool do_export_map = false;
+  
+  opterr = 0; // handle errors ourselves
+  while (1)
+    {
+      static struct option longOptions[] =
+	{
+	  {"help",           no_argument,       0, 'h'},
+	  {"map",            required_argument, 0, 'm'},
+//	  {"export-scripts", required_argument,       0, 'e'},
+//	  {"file-map",        required_argument,       0, 'f'},
+	  {"version",        no_argument,       0, 'v'},
+	  {0, 0, 0, 0}
+	};
+      /* `getopt_long' stores the option index here. */
+      int option_index = 0;
+
+      // the + below tells getopt_long not to reorder argv
+      int c = getopt_long (argc, argv, "+hm:v", longOptions, &option_index);
+      /* detect the end of the options */
+      if (c == -1)
+	break;
+      switch (c)
+	{
+	case '?':
+	  break; // ignore unknown options
+	case 'h':
+	  usage (rank);
+	case 'm':
+	  do_print_map = true;
+	  continue;
+/*	case 'e':
+	  do_export_scripts = true;
+	  continue;
+	case 'f':
+		do_export_map = true;
+	  continue;*/
+	case 'v':
+	  print_version (rank);
+
+	default:
+	  abort ();
+	}
+    }
+
+  // extract the configuration file name using
+  // mpi implementation dependent code from ../mpidep
+  std::istream* configFile = getConfig (rank, argc, argv);
+
+  if (!*configFile)
+    {
+      if (rank <= 0)
+	std::cerr << "MUSIC: Couldn't open configuration file "
+		  << argv[1] << std::endl;
+      exit (1);
+    }
+
+  MUSIC::Configuration config;
+  MUSIC::ApplicationMapper mapper (&config);
+  mapper.map (configFile, rank);
+  if (do_print_map)
+    {
+      if (rank <= 0)
+	print_map (&config);
+    }
+
+  /*  if (do_export_scripts)
+    {
+      if (rank <= 0)
+	export_scripts (&map);
+    }
+  if(do_export_map)
+  {
+	  if (rank <=0)
+		  export_map(&map);
+
+  }*/
+  if (do_print_map) //|| do_export_scripts || do_export_map)
+    return 0;
+  
+  if (rank == -1)
+    {
+      std::cerr << "MUSIC: Unable to determine process rank." << std::endl
+		<< "MUSIC: Did you launch music using mpirun?" << std::endl
+		<< "MUSIC: If so, check the comments about porting in README." << std::endl;
+      exit (1);
+    }
+
+  launch (&config, argv);
+
+  return 0;
+}
diff --git a/utils/viewevents.cpp b/utils/viewevents.cpp
new file mode 100644
index 0000000..dbbd8f1
--- /dev/null
+++ b/utils/viewevents.cpp
@@ -0,0 +1,36 @@
+/*
+ *  This file is part of MUSIC.
+ *  Copyright (C) 2009 INCF
+ *
+ *  MUSIC 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; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  MUSIC 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 should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// viewevents.cpp written by Johannes Hjorth, hjorth@nada.kth.se
+
+
+#include "VisualiseNeurons.h"
+#include <iostream>
+#include <sstream>
+#include <string>
+
+int main(int argc, char **argv) {
+
+  VisualiseNeurons *vn = new VisualiseNeurons();
+  vn->run(argc,argv);
+
+  std::cout << "Done." << std::endl;
+
+  vn->finalize();
+
+}
-- 
GitLab